Main Tutorials

Java 8 Optional In Depth

Java 8 has introduced a new class Optional in java.util package. It is used to represent a value is present or absent. The main advantage of this new construct is that No more too many null checks and NullPointerException. It avoids any runtime NullPointerExceptions and supports us in developing clean and neat Java APIs or Applications. Like Collections and arrays, it is also a Container to hold at most one value. Let us explore this new construct with some useful examples.

Advantages of Java 8 Optional:

  1. Null checks are not required.
  2. No more NullPointerException at run-time.
  3. We can develop clean and neat APIs.
  4. No more Boiler plate code

1. Optional Basic example

Optional.ofNullable() method returns a Non-empty Optional if a value present in the given object. Otherwise returns empty Optional.

Optionaal.empty() method is useful to create an empty Optional object.

OptionalBasicExample.java

package com.mkyong;

import java.util.Optional;

public class OptionalBasicExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        String answer1 = "Yes";
        String answer2 = null;

        System.out.println("Non-Empty Optional:" + gender);
        System.out.println("Non-Empty Optional: Gender value : " + gender.get());
        System.out.println("Empty Optional: " + Optional.empty());

        System.out.println("ofNullable on Non-Empty Optional: " + Optional.ofNullable(answer1));
        System.out.println("ofNullable on Empty Optional: " + Optional.ofNullable(answer2));
        
        // java.lang.NullPointerException
        System.out.println("ofNullable on Non-Empty Optional: " + Optional.of(answer2));

    }

}

Output


Non-Empty Optional:Optional[MALE]
Non-Empty Optional: Gender value : MALE
Empty Optional: Optional.empty

ofNullable on Non-Empty Optional: Optional[Yes]
ofNullable on Empty Optional: Optional.empty

Exception in thread "main" java.lang.NullPointerException
	at java.util.Objects.requireNonNull(Objects.java:203)
	at java.util.Optional.<init>(Optional.java:96)
	at java.util.Optional.of(Optional.java:108)
	//...

2. Optional.map and flatMap

OptionalMapFlapMapExample.java

package com.mkyong;

import java.util.Optional;

public class OptionalMapFlapMapExample {

    public static void main(String[] args) {

        Optional<String> nonEmptyGender = Optional.of("male");
        Optional<String> emptyGender = Optional.empty();

        System.out.println("Non-Empty Optional:: " + nonEmptyGender.map(String::toUpperCase));
        System.out.println("Empty Optional    :: " + emptyGender.map(String::toUpperCase));

        Optional<Optional<String>> nonEmptyOtionalGender = Optional.of(Optional.of("male"));
        System.out.println("Optional value   :: " + nonEmptyOtionalGender);
        System.out.println("Optional.map     :: " + nonEmptyOtionalGender.map(gender -> gender.map(String::toUpperCase)));
        System.out.println("Optional.flatMap :: " + nonEmptyOtionalGender.flatMap(gender -> gender.map(String::toUpperCase)));
        
    }

}

Output


Non-Empty Optional:: Optional[MALE]
Empty Optional    :: Optional.empty
Optional value   :: Optional[Optional[male]]
Optional.map     :: Optional[Optional[MALE]]
Optional.flatMap :: Optional[MALE]

3. Optional.filter

OptionalFilterExample.java

package com.mkyong;

import java.util.Optional;

public class OptionalFilterExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        //Filter on Optional
        System.out.println(gender.filter(g -> g.equals("male"))); //Optional.empty
        System.out.println(gender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional[MALE]
        System.out.println(emptyGender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional.empty

    }

}

Output


Optional.empty
Optional[MALE]
Optional.empty

4. Optional isPresent and ifPresent

Optional.isPresent() returns true if the given Optional object is non-empty. Otherwise it returns false.

Optional.ifPresent() performs given action if the given Optional object is non-empty. Otherwise it returns false.

OptionalIfPresentExample.java

package com.mkyong;

import java.util.Optional;

public class OptionalIfPresentExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        if (gender.isPresent()) {
            System.out.println("Value available.");
        } else {
            System.out.println("Value not available.");
        }

        gender.ifPresent(g -> System.out.println("In gender Option, value available."));

        //condition failed, no output print
        emptyGender.ifPresent(g -> System.out.println("In emptyGender Option, value available."));

    }

}

Output


Value available.
In gender Option, value available.

5. Optional orElse methods

It returns the value if present in Optional Container. Otherwise returns given default value.

OptionalOrElseExample.java

package com.mkyong;

import java.util.Optional;

public class OptionalOrElseExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        System.out.println(gender.orElse("<N/A>")); //MALE
        System.out.println(emptyGender.orElse("<N/A>")); //<N/A>

        System.out.println(gender.orElseGet(() -> "<N/A>")); //MALE
        System.out.println(emptyGender.orElseGet(() -> "<N/A>")); //<N/A>

    }

}

Output


MALE
<N/A>
MALE
<N/A>

6. Without Java 8 Optional

As everyone is familiar with Online Shopping. Let us assume that we want to implement a Mobile Product Module for a famous e-Commerce website.

Let us implement Mobile Domain module Without Java 8 Optional.

ScreenResolution.java

package com.mkyong.without.optional;

public class ScreenResolution {

	private int width;
	private int height;
	
	public ScreenResolution(int width, int height){
		this.width = width;
		this.height = height;
	}
	
	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}
	
}
DisplayFeatures.java

package com.mkyong.without.optional;

public class DisplayFeatures {

	private String size; // In inches
	private ScreenResolution resolution;
	
	public DisplayFeatures(String size, ScreenResolution resolution){
		this.size = size;
		this.resolution = resolution;
	}
	
	public String getSize() {
		return size;
	}
	public ScreenResolution getResolution() {
		return resolution;
	}
	
}
Mobile.java

package com.mkyong.without.optional;

public class Mobile {

	private long id;
	private String brand;
	private String name;
	private DisplayFeatures displayFeatures;
	// Likewise we can see Memory Features, Camera Features etc.
	
	public Mobile(long id, String brand, String name, 
                            DisplayFeatures displayFeatures){
		this.id = id;
		this.brand = brand;
		this.name = name;
		this.displayFeatures = displayFeatures;
	}

	public long getId() {
		return id;
	}

	public String getBrand() {
		return brand;
	}

	public String getName() {
		return name;
	}

	public DisplayFeatures getDisplayFeatures() {
		return displayFeatures;
	}
	
}

Here if we observe getMobileScreenWidth() method, it has lot of boiler plate code with lots null checks. Before Java 8, we should do all these non-sense stuff to avoid Runtime NullPointerExceptions.

MobileService.java

package com.mkyong.without.optional;

public class MobileService {
	
	public int getMobileScreenWidth(Mobile mobile){

		if(mobile != null){
			DisplayFeatures dfeatures = mobile.getDisplayFeatures();
			if(dfeatures != null){
				ScreenResolution resolution = dfeatures.getResolution();
				if(resolution != null){
					return resolution.getWidth();
				}
			}
		}
		return 0;

	}

}

Develop one test application to test these Domain objects.

MobileTesterWithoutOptional.java

package com.mkyong.without.optional;

public class MobileTesterWithoutOptional {
	
	public static void main(String[] args) {

		ScreenResolution resolution = new ScreenResolution(750,1334);
		DisplayFeatures dfeatures = new DisplayFeatures("4.7", resolution);
		Mobile mobile = new Mobile(2015001, "Apple", "iPhone 6s", dfeatures);
		
		MobileService mService = new MobileService();
		
		int mobileWidth = mService.getMobileScreenWidth(mobile);
		System.out.println("Apple iPhone 6s Screen Width = " + mobileWidth);
		
		ScreenResolution resolution2 = new ScreenResolution(0,0);
		DisplayFeatures dfeatures2 = new DisplayFeatures("0", resolution2);
		Mobile mobile2 = new Mobile(2015001, "Apple", "iPhone 6s", dfeatures2);		
		int mobileWidth2 = mService.getMobileScreenWidth(mobile2);
		System.out.println("Apple iPhone 16s Screen Width = " + mobileWidth2);

	}

}

Output


Apple iPhone 6s Screen Width = 750
Apple iPhone 16s Screen Width = 0

7. With Java 8 Optional

Now develop same domain models using Java 8 Optional construct with clean and neat way.

P.S ScreenResolution.java no change. Please refer above section.

DisplayFeatures.java

package com.mkyong.with.optional;

import java.util.Optional;

public class DisplayFeatures {

	private String size; // In inches
	private Optional&lt;ScreenResolution&gt; resolution;
	
	public DisplayFeatures(String size, Optional<ScreenResolution> resolution){
		this.size = size;
		this.resolution = resolution;
	}
	
	public String getSize() {
		return size;
	}
	public Optional<ScreenResolution> getResolution() {
		return resolution;
	}
	
}
Mobile.java

package com.mkyong.with.optional;

import java.util.Optional;

public class Mobile {

	private long id;
	private String brand;
	private String name;
	private Optional&lt;DisplayFeatures&gt; displayFeatures;
	// Like wise we can see MemoryFeatures, CameraFeatures etc.
	// For simplicity, using only one Features
	
	public Mobile(long id, String brand, String name, Optional&lt;DisplayFeatures&gt; displayFeatures){
		this.id = id;
		this.brand = brand;
		this.name = name;
		this.displayFeatures = displayFeatures;
	}

	public long getId() {
		return id;
	}

	public String getBrand() {
		return brand;
	}

	public String getName() {
		return name;
	}

	public Optional&lt;DisplayFeatures&gt; getDisplayFeatures() {
		return displayFeatures;
	}
	
}

Here we can observe that how clean our getMobileScreenWidth() API without null checks and boiler plate code. We don not worry about NullPointerExceptions at run-time.

MobileService.java

package com.mkyong.with.optional;

import java.util.Optional;

public class MobileService {

  public Integer getMobileScreenWidth(Optional<Mobile> mobile){
	return mobile.flatMap(Mobile::getDisplayFeatures)
		 .flatMap(DisplayFeatures::getResolution)
		 .map(ScreenResolution::getWidth)
		 .orElse(0);

  }

}

Now develop one test component

MobileTesterWithOptional.java

package com.mkyong.with.optional;

import java.util.Optional;

public class MobileTesterWithOptional {
	
  public static void main(String[] args) {
	ScreenResolution resolution = new ScreenResolution(750,1334);
	DisplayFeatures dfeatures = new DisplayFeatures("4.7", Optional.of(resolution));
	Mobile mobile = new Mobile(2015001, "Apple", "iPhone 6s", Optional.of(dfeatures));
		
	MobileService mService = new MobileService();
		
	int width = mService.getMobileScreenWidth(Optional.of(mobile));
	System.out.println("Apple iPhone 6s Screen Width = " + width);

	Mobile mobile2 = new Mobile(2015001, "Apple", "iPhone 6s", Optional.empty());		
	int width2 = mService.getMobileScreenWidth(Optional.of(mobile2));
	System.out.println("Apple iPhone 16s Screen Width = " + width2);
  }
}

Output


Apple iPhone 6s Screen Width = 750
Apple iPhone 16s Screen Width = 0

8. Where does Java Optional fits?

If we observe above real-time Retail Domain use-case, we should know that Java Optional construct is useful at the following places.

8.1 Method Parameter


public void setResolution(Optional<ScreenResolution> resolution) {
	this.resolution = resolution;
}

8.2 Method Return Type


public Optional<ScreenResolution> getResolution() {
	return resolution;
}

8.3 Constructor Parameter


public DisplayFeatures(String size, Optional<ScreenResolution> resolution){
	this.size = size;
	this.resolution = resolution;
}

8.4 Variable Declaration


private Optional<ScreenResolution> resolution;

8.5 Class Level


public class B

public class A<T extends Optional<B>> { }

Download Source Code

Download – Java8Optional-example.zip (4 KB)

References

  1. OptionalJavaDoc

About Author

author image
Rambabu Posa have 12+ years of RICH experience as Sr Agile Lead Java/Scala/BigData/NoSQL Developer. Apart from Java and Java EE, he is good at Spring, Hibernate, RESTful WebServices, NoSQL, BigData Hadoop Stack, Cloud, Scala, Groovy, Play Framework, Akka, TDD, BDD,Agile and much more. He likes sharing his knowledge through writing tutorials.

Comments

Subscribe
Notify of
26 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Sandeep
6 years ago

The usage of Optional in the mobile example is wrong, please go through this article https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type/26328555#26328555 where Brian Goetz (developer in Oracle) clearly mentions not to use Optional field and method parameters.

Also in future before posting articles please go through the best practices.

DonJohn
6 years ago
Reply to  Sandeep

How is correct then?

L@xm!
6 years ago
Reply to  Sandeep

Correct

Grzegorz Piwowarek
6 years ago

Should be “flatMap” instead of “flapMap” 🙂

EvanR
3 years ago

Other than iterating over an optional collection, I don’t see any advantage to using an Optional with a single return value. You don’t test for null, but you do have to check for empty (potentially more byte code and runtime overhead due to a function call?). Then you need to dereference the Optional to get the value (more byte code, more time?). And you don’t have to worry about NullPointerException but you’re just substituting with having to worry about NoSuchElementException.

dfg12
3 years ago

What is use of the ‘extends’ in the statement?
public class A<T extends Optional<B>> { }
Optional is final.

Mike
4 years ago

You should never ever put an Optional (neither a Stream) in a Class. Those are not serializable and this is by design. Optional should only be returned from a method. It is here to control the flow of execution, not as a storage class.

sandsio2
4 years ago

From section 5 .Optional orElse

below code throw NullPointerException if Optional.of(null) , whats the point of Optional and orElse
Optional gender = Optional.of(null);
System.out.println(gender.orElse(“”)); //MALE

Srinivas Gangaraju
4 years ago
Reply to  sandsio2

Use ofNullable. when u already know that the value is going to be null. what is the point of initialising with one. This is well used in a situation where the returned value is going to be null or some value. Based on which u could perform some operation.
in ur code use

Optional gender = Optional.ofNullable(null);
System.out.println(opt.orElse(“Male”));//if optional holds string types

Nicolae
5 years ago

OMG, please never send an Optional to a method or constructor! This is totally wrong.
The Optional should be used as return type only. The callee should inform the caller that the return value might be missing, not vice-versa.

Patrick Raab
6 years ago

@Rambabu Posa,

First of all thank u for this simple but usefull example.
I found a small mistake:

Optionaal.empty() method is useful to create an empty Optional object.

the Optional.empty is spelled wrong ^^

have a nice Day tho 🙂

Greetz from Germany

Cristi Georgescu
7 years ago

I am a bit confused why you would use “public void setResolution(Optional resolution)” when you can do a Optional.fromNullable(resolution) on the get if you really want to. I would say it’s not worth it to accept as input an Optional.

Rambabu Posa
7 years ago

Thanks for reading my post.
If you observe my examples, I didn’t use that code snippet. I just took that example to explain how we can use a Optional as a Method parameter. It may not be a Setter Method any thing like:

Optional flatMap(Function<? super T,Optional> mapper) from Optional class.

Ram

Vinod Kumar
4 years ago

Its amazing post on Optional. Thanks for sharing

Vinod Kumar
4 years ago

Its amazing post on Optional. Thanks for sharing!

Guest
4 years ago

Is this more clear?

    @Test
    public void TestDate() {

        String message = "Hello World!";
        System.out.println("message -> " + message + "\n");

        Optional genderOptional = Optional.of(message);
        System.out.println("Optional.of(message) -> " + genderOptional);
        System.out.println("Optional.of(message).get() -> " + genderOptional.get());
        try {
            Optional.of(null);
        } catch (java.lang.NullPointerException e) {
            System.out.println("Optional.of(null) -> java.lang.NullPointerException \n");
        }

        System.out.println("Optional.empty() -> " + Optional.empty() + "\n");

        System.out.println("Optional.ofNullable(null) -> " + Optional.ofNullable(null));
        System.out.println("Optional.ofNullable(message) -> " + Optional.ofNullable(message));
        System.out.println("Optional.ofNullable(message).get() -> " + Optional.ofNullable(message).get());

    }

Output

message -> Hello World!

Optional.of(message) -> Optional[Hello World!]
Optional.of(message).get() -> Hello World!
Optional.of(null) -> java.lang.NullPointerException 

Optional.empty() -> Optional.empty

Optional.ofNullable(null) -> Optional.empty
Optional.ofNullable(message) -> Optional[Hello World!]
Optional.ofNullable(message).get() -> Hello World!

Umesh Mehta
4 years ago

I am confused with the comment “We do not worry about NullPointerExceptions at run-time”, and the reason is if somehow mobile object or dfeatures object is null then it throws the NullPointerExceptions, where as with the Null check (defined in MobileService.java of Without Java 8 Optional) you will always get ZERO as result.
Can someone please clarify this.

Thanks In advance

Umesh Mehta
4 years ago
Reply to  Umesh Mehta

I got ans, we have to use Optional.ofNullable instead of Optional.of

Brendan
6 years ago

Typo
Optionaal.empty()

suseela
6 years ago

How can we avoid null pointer exception using Optional ??
I didn’t get it.

Vinod Kumar
4 years ago
Reply to  suseela

You can use something like this:
Optional nullTest = Optional.empty();
nullTest.orElseThrow(Exception::new);

EvanR
3 years ago
Reply to  Vinod Kumar

This is basically the same as doing a null check. You haven’t gained anything by introducing an extra layer of encapsulation.

Nicolae
5 years ago
Reply to  suseela

When a method returns an Optional, then you are forced to first check if the value is present, and only then get it:

If userId is not present in the database then the above function returns null.
User user = findUserById(“667290”);

Here you are trying to get the name of the user? What if the user is null?, a NullPointerException is thrown.
System.out.println(“User’s Name = ” + user.getName());

Now, let’s see how Optional will help you mitigate the risk of running into NullPointerException:
Optional findUserById(String userId) { … };

By returning Optional from the method, we have made it clear to the clients of this method that there might not be a User with the given userId.

EvanR
3 years ago
Reply to  Nicolae

You have to check for empty() instead of checking for null.
If you don’t check for empty you can get a NoSuchElementException instead of NPE but you still get an exception.
Functionally, there’s no difference and you’ve added an extra level of encapsulation, object allocation/initialization/recovery, an extra dereference to get your actual value, and the potential run time overhead of the call to empty().
Although Optional is a bit more self-explanatory it comes at a memory and speed cost, both of which are critical for high performance systems

Sello Mtshali
6 years ago

Nice. Thanks!