Optional

PROBLEM

public Foo doSomething() {
    return null; 
}


Foo foo = doSomething();
if (foo == null) {
    // handle null case...
}
else {
    // do something with the foo object...
}

SOLUTION

public Optional<Foo> doSomething() {

	Optional<Foo> foo = Optional.of(new Foo());  // populated Optional
	Optional<Foo> foo = Optional.of(null);      // throws NullPointerException
	
	// Right way
	Optional<Foo> foo1 = Optional.ofNullable(new Foo());  // populated Optional
	Optional<Foo> foo2 = Optional.ofNullable(null);       // empty Optional
	
	Optional<Foo> populated = // ...populated Optional...
	populated.isPresent();    // true
	populated.isEmpty();      // false	
	

}

Foo foo = doSomething()
		.orElse(new Foo());
		
Foo foo = doSomething()
		.orElseThrow(SomeException::new);		
		
// we must use additional methods
Foo foo = doSomething();  // - will not compile

Optional<Foo> possibleFoo = doSomething();

Foo foo = possibleFoo
		.orElseGet(() -> { /* ...lazily create a Foo object... */ });
		
possibleFoo.ifPresent(foo -> { /* ...do something with foo... */ });		

possibleFoo.ifPresentOrElse(
    foo -> { /* ...do something with foo... */ },
    () -> { /* ...do something when no foo found... */ }
);

// for Example

public Optional<Bar> findBar() {
    // ...return a populated Bar if it could be found...
}

findBar().ifPresent(bar -> bar.update());
If a null value is returned in place of an Optional object, this is a breach of the method contract on the part of the method developer. By stating that a method will return an Optional object, the method developer is also stating that it is invalid to return null. Since the Optional object denotes the possibility of a missing object, there is no valid use case for a null value (i.e., the method should return an empty Optional instead of null in all cases). Therefore, whenever we are dealing with an Optional object, we are right to assume that the Optional object will never be null. Although it is possible that the Optional object can be null in practice, this is a problem that should be resolved by the method developer rather than the client.