Issue
Need help with how java 11 new feature can be used (var with lambda expression). Old way of using streams
var listString = new ArrayList<>(Arrays.asList(new String[] {"a", "ab", "cd", null}));
long result = listString.stream().filter(x -> x != null && x.contains("a")).count();
System.out.println(result); //2
New java 11 code var with lambda expression
var listString = new ArrayList<>(Arrays.asList(new String[] {"a", "ab", "cd", null}));
long result = listString.stream().filter((@NonNull var x) -> x.contains("a")).count();
System.out.println(result); //null pointer exception
Advantage: Annotations can be applied on local variables (using var) like nonnull or final. Which was not possible in older versions of java (Below 9)
Now my new code doesn't seem to work even after adding NonNull annotation (Throws null pointer exception). However I need to add one extra condition to make it work (just like old way)
var listString = new ArrayList<>(Arrays.asList(new String[] {"a", "ab", "cd", null}));
long result = listString.stream().filter((@NotNull var x) -> x != null && x.contains("a")).count();
System.out.println(result); //2
Now I don't find any advantage of new way of coding in java 11. Can somebody tell me scenario on how the new way of coding really helps developers ?
Solution
You're assuming that adding a @NonNull
annotation will magically filter out nulls. That is not how things work, and an explicit null check remains necessary unless you prevent nulls from entering in the first place.
@NonNull
is either used by a validation framework (not applicable for a parameter of a lambda AFAIK), or a hint for static analyzers to suggest incorrect usages (e.g. if it is possible null is actually passed, or performing unnecessary null-checks while you declared something is not null).
Personally, I don't think using var
in a lambda will be a very useful use case, it just automatically follows from the fact that since (String x) -> ....
and x -> ...
are a valid lambda for a call site, so is (var x) -> ...
(as a type can be inferred).
As detailed in JEP 323: Local-Variable Syntax for Lambda Parameters:
For uniformity with local variables, we wish to allow 'var' for the formal parameters of an implicitly typed lambda expression
and
For formal parameters of implicitly typed lambda expressions, allow the reserved type name var to be used, so that:
(var x, var y) -> x.process(y)
is equivalent to:
(x, y) -> x.process(y)
An implicitly typed lambda expression must use var for all its formal parameters or for none of them.
And yes, the JEP lists being able to annotate the var
as a benefit, but this is no different from what was already possible for explicitly typed lambdas: (@NonNull String x) -> ...
, it now just also allows it for implicitly typed lambdas.
Adding such annotations in general only has benefit for documentation, static analyzers and maybe for some code-generating annotation processors. Annotations in Java by themselves do nothing, they need an annotation processor or reflection to actually have any effect.
Answered By - Mark Rotteveel
Answer Checked By - David Marino (JavaFixing Volunteer)