Reputation: 196
I am new to Java 8 and trying out Null type annotations and Optional.
For my example below, I have used String rather than my class and am calling toUpperCase just to call something, in my case I actually call a function passing in a parameter (so don't think I can use :: operator and/or maps).
In Eclipse I have the Java - Compiler - Errors/Warnings - Null Analysis Errors turned on.
My test code below:
public void test1(@Nullable String s) {
// the 2nd s2 has a Potential null pointer access error.
// I was hoping ifPresent would imply NonNull
Optional.ofNullable(s).ifPresent(s2 -> s2.toUpperCase());
}
@Nullable
public String getSomeString() {
return null;
}
public void test2() {
String s = getSomeString();
// This is fine, unlike the first example, I would have assumed that
// it would know s was still nullable and behave the same way.
Optional.ofNullable(s).ifPresent(s2 -> s2.toUpperCase());
}
It would seem that using Eclipse type null annotations and Optional.ifPresent doesn't go well together.
Am I wasting my time trying to get something like this to work? Should I just revert back to assigning the getter to a temp var then checking if null, and if not call my function?
Upvotes: 2
Views: 1587
Reputation: 8178
JDT's null analysis cannot know about the semantics of each and every method in JRE and other libraries. Therefore, no conclusions are drawn from seeing a call to ifPresent
. This can be remedied by adding external annotations to Optional
so that the analysis will see method ofNullable
as
<T> Optional<@NonNull T> ofNullable(@Nullable T value)
External annotations are supported starting with Eclipse Mars, released June, 24, 2015. See Help: Using external null annotations.
The difference between the two variants in the question is due to how null analysis is integrated with Java 8 type inference: In variant (1) s
has type @Nullable String
. When this type is used during type inference, it is concluded that the argument to ifPresent
is nullable, too. In variant (2) s
has type String
(although flow analysis can see that is may be null after the initialization from getSomeString
). The unannotated type String
is not strong enough to aid type inference to the same conclusion as variant (1) (although this could possibly be improved in a future version of JDT).
Upvotes: 2
Reputation: 8068
First of: @Nullable
seams not to be part of the public Java 8 SDK. Have a look at the package you imported: com.sun.istack.internal.Nullable
.
Second: I have run both of your methods: test1(null)
and test2()
and nothing out of the ordinary happened. Everything was fine (as expected). So what did you observe?
run test1(null)
=> no execution of lambda expression.
run test2() => no execution of lambda expression.
I changed your code for testing in the following way:
public void test1(@Nullable String s) {
Optional.ofNullable(s).ifPresent(s2 -> System.out.println("executed"));
}
public void test2() {
String s = getSomeString();
Optional.ofNullable(s).ifPresent(s2 -> System.out.println("executed"));
}
Upvotes: 1