How to use @Nullable and @Nonnull annotations more effectively?
Short answer: I guess these annotations are only useful for your IDE to warn you of potentially null pointer errors.
As said in the "Clean Code" book, you should check your public method's parameters and also avoid checking invariants.
Another good tip is never returning null values, but using Null Object Pattern instead.
Other than your IDE giving you hints when you pass null
to methods that expect the argument to not be null, there are further advantages:
- Static code analysis tools can test the same as your IDE (e.g. FindBugs)
- You can use Aspect-oriented programming (AOP) to check these assertions
This can help your code be more maintainable (since you do not need null
checks) and less error-prone.
I think this original question indirectly points to a general recommendation that run-time null-pointer check is still needed, even though @NonNull is used. Refer to the following link:
Java 8's new Type Annotations
In the above blog, it is recommended that:
Optional Type Annotations are not a substitute for runtime validation Before Type Annotations, the primary location for describing things like nullability or ranges was in the javadoc. With Type annotations, this communication comes into the bytecode in a way for compile-time verification. Your code should still perform runtime validation.
Compiling the original example in Eclipse at compliance 1.8 and with annotation based null analysis enabled, we get this warning:
directPathToA(y);
^
Null type safety (type annotations): The expression of type 'Integer' needs unchecked conversion to conform to '@NonNull Integer'
This warning is worded in analogy to those warnings you get when mixing generified code with legacy code using raw types ("unchecked conversion"). We have the exact same situation here: method indirectPathToA()
has a "legacy" signature in that it doesn't specify any null contract. Tools can easily report this, so they will chase you down all alleys where null annotations need to be propagated but aren't yet.
And when using a clever @NonNullByDefault
we don't even have to say this every time.
In other words: whether or not null annotations "propagate very far" may depend on the tool you use, and on how rigorously you attend to all the warnings issued by the tool. With TYPE_USE null annotations you finally have the option to let the tool warn you about every possible NPE in your program, because nullness has become an intrisic property of the type system.