Reputation: 31
I am trying to make a use case for the Java 11 extension on var keyword for lambda expressions. The examples I could find online are always related to @NonNull annotation. However when I want to do something like this:
long count = Stream.of(-3, -2, -1, 0, 1, 2, 3, 4)
.filter((@NegativeOrZero var a) -> a > -3)
.count();
System.out.println(count);
I get:
7
I expect to count only -2, -1 and 0 and not count others, or throw an error or something. Same goes for the following:
long count = Stream.of(1, 2, 3, 4, 5, null, 7, 8, 9)
.filter((@NotNull(message="It is a null!!") var a) -> a > 5)
.count();
System.out.println(count);
I get an NPE without any custom message unless I change a > 5
to a != null && a > 5
which is not related to annotation.
Can someone explain what am I missing here?
Edit: Maybe I forgot to mention but can you provide an example with var keyword and validations combined to understand its benefits?
Edit 2: I found a more simple example that is supposed to throw an error. However, for me, it returns true. I am using JDK 13 btw.
Predicate<String> predicate = (@NotNull var a) -> true;
System.out.println(predicate.test(null));
Upvotes: 3
Views: 1008
Reputation: 25176
One of the possible use cases to pre-filter null values with Local-Variable Syntax for Lambda Parameters can be done by using JetBrains annotations.
https://mvnrepository.com/artifact/org.jetbrains/annotations/18.0.0
import org.jetbrains.annotations.NotNull;
...
public static void main(String[] args) {
long cnt = Stream.of(2, 4, 6, 8, 10, null, 1)
.filter((@NotNull var i) -> i > 5)
.count();
System.out.println(cnt);
}
Will yield IllgalArgumentException
instead of NullPointerException
at runtime:
Exception in thread "main" java.lang.IllegalArgumentException: Argument for @NotNull parameter 'i' of com/app/App.lambda$main$0 must not be null
at com.app.App.$$$reportNull$$$0(App.java)
at com.app.App.lambda$main$0(App.java)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176)
As said at this time javax.constraint.*
annotations won't be automagically performed as a validation against the lambda parameter. With time, I'm sure, more and more libraries, such as static code analyzers or compile time checker tools, will leverage http://openjdk.java.net/jeps/323 feature and will support that.
Upvotes: 1
Reputation: 44970
java.util.stream
classes are not in any way related to javax.validation
so the stream won't understand or process @NotNull
or @NegativeOrZero
. When you annotate type you only provide the metadata. Something has to process this metadata to create the desired behavior, and stream does not.
Your examples are evaluated as:
Stream.of(-3, -2, -1, 0, 1, 2, 3, 4)
.filter((var a) -> a > -3)
.count(); // 7 as only -3 is filtered out
Stream.of(1, 2, 3, 4, 5, null, 7, 8, 9)
.filter((var a) -> a > 5) // NPE on boxing null
.count();
Upvotes: 2