Best practices in Java development circa 2021 dictate sparing use of null
. Kotlin even makes you do extra work to declare a nullable reference type. In Kotlin, by default, variables with reference-type cannot have a null
value.
Unfortunately we Geode developers maintain a lot of code that was not developed that way. As a result, as maintainers, we often find ourselves wondering whether a particular variable can take on a null value at runtime. One approach is to always assume every reference-typed variable can be null
. But that leads to needlessly verbose code.
With GEODE-8882 we have introduced a compile-time dependency (in the geode-core
subproject) on the JetBrains annotations package. This makes the JetBrains @NotNull
and @Nullable
annotations available in classes in that subproject. If you need those annotations in other subprojects, just add this to the pertinent build.gradle
:
compileOnly('org.jetbrains:annotations')
These annotations can help you declare your intentions in new code but they are particularly helpful during refactoring. If you wonder whether a variable or method parameter can ever be null
, you can annotate it with @NotNull
and IntelliJ will perform static analysis (inspection) and will point out (as a warning) places where that variable or parameter is taking on a potentially-null value.
Here are instructions from JetBrains on how the annotations work in the IDE: IntelliJ Support for @Nullable and @Not Null Annotations
If you set up your IDE this way then you will see IllegalArgumentExceptions
when tests encounter violations of @NotNull
at runtime. This runtime checking is not, in general, in effect in the Geode product unless the user goes out of their way to make it so, by adding a Java annotation processor.
Here is the home page for the JetBrains annotations Maven project: https://github.com/JetBrains/java-annotations
Example
Here's an example. I annotated the clientVersion
parameter to writeHandshakeMessage
this way:
public void writeHandshakeMessage(DataOutputStream dos, byte type, String p_msg, @NotNull final KnownVersion clientVersion, byte endpointType, int queueSize) throws IOException {
Here is the IDE highlighting a situation where an (indirect) caller may be passing null
:
Under "More actions" I pick "Navigate to 'null' argument usages":
…where I find this call-site passing a null
for clientVersion
:
I could've found this without IDE support. But in this case, I didn't find it until I leveraged the IDE support.