Gadam
Gadam

Reputation: 3024

Optional Type returns a null value

I have a class like this.

public class SomeClass {

  private Optional<String> testString;

  public SomeClass() { 
      populateFields();
  }

  public Optional<String> getTestString() {
      return testString;
  }

  private void populateFields() {
     if(//something is going false here){
       testString = functionThatReturnsOptionalString();
     }
  }

}

Now instanceOfSomeClass.getTestString() returns null. Isn't Optional always supposed to contain a non-null value or be empty? I am trying or avoid isNull() and just use isEmpty() in my caller.

If I put a breakpoint on the first line of populateFields() and check the value in testString at that time, it shows the value as null. Meaning the default value for this field(before being assigned anything) is null.

Please shed light on this situation; and maybe the correct usage of Optional?

Upvotes: 12

Views: 62894

Answers (5)

Mario Rossi
Mario Rossi

Reputation: 7799

That's because your first need an object of class Optional<String> and the code has only a reference of type Optional<String>, which is null as long as you don't initialize it. Declare (and initialize) testString with an empty/absent value in the following way:

private Optional<String> testString= Optional<String>.empty() ;

Or using type inference:

private Optional<String> testString= Optional.empty<>() ;
private Optional testString= Optional.empty<String>() ;

Now you have an actual Optional object attached to reference testString instead of null. Java 10 would allow the even shorter

private var testString= Optional.empty<String>() ;

If you already have a String value to start with (let's call it originalString), there are 3 main options:

  1. Initialize testString with private Optional<String> testString= Optional.of(originalString) ; (which would produce a NullPointerException if originalString is null)
  2. Use Optional.ofNullable(originalString) instead, which produces an empty/absent Optional if originalString is null.
  3. Refer to originalString in method getTestString directly through one of the two previous methods (return Optional.ofNullable(originalString) ;, for example). No need for a testString member. I actually do not generally recommend this practice.

Bottom line, while an actual Optional object can not contain a null value, a reference to an Optional definitely can (especially when not initialized). As a rule of thumb, Optional references should always be initialized with Optional.empty() if not an actual "present"/"non-empty" value.

Upvotes: -1

Louis Wasserman
Louis Wasserman

Reputation: 198083

An Optional always contains a non-null value or is empty, yes, but you don't have an Optional, you have a reference of type Optional pointing to null. You need to initialize testString, e.g. to Optional.empty().

Optional isn't magic, it's an object like any other, and the Optional reference itself can be null. It's the contents of the Optional that can't be null.

Upvotes: 36

Quanturium
Quanturium

Reputation: 5696

From the Java documentation:

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

Although the constructor of YourClass does not instantiate your Optional class which is why it is null.

public SomeClass() {  
    this.testString = Optional.empty();
} 

source: http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

Upvotes: 1

Dogs
Dogs

Reputation: 3157

I always like to store the internal fields of the class as their actual values, and use return Optional.ofNullable(theField) in the getter method. This ensures that the method will always return some type of optional. In other words, you never run into the situation where your method which is supposed to return an optional is returning null.

So in your case:

private String testString;

...

public Optional<String> getTestString() {
      return Optional.ofNullable(testString);
}

In additional to the 'never returning null' benefit, this approach should also be more behaved when using things like Gson to marshal instances of your class into a format like JSON. I haven't tried Gson with Java 8 optionals, but with Guava optionals they don't serialize very nicely into JSON without a type adapter. If you're storing the raw value and then wrapping them with Optionals at your getter methods, they serialize into JSON in just the manner you would expect.

Upvotes: 1

Samuel Rondeau-Millaire
Samuel Rondeau-Millaire

Reputation: 1130

From the oracle documentation for the Optional type :

A container object which may or may not contain a non-null value.

So, yes it will return null if the variable is set to null. More info here

Upvotes: 1

Related Questions