Reputation: 3024
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
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:
testString
with private Optional<String> testString= Optional.of(originalString) ;
(which would produce a NullPointerException
if originalString
is null
)Optional.ofNullable(originalString)
instead, which produces an empty/absent Optional
if originalString
is null
.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
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
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
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
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