+1
In summary:
- We could use only
@Nullable. It just means that SonarQube will not check that calling code verifies that the return value used is not null. However SonarQube still throws an issue if it sees that the return value can be null if there’s no@Nullableannotation for it. - We could use both
@CheckForNulland@Nullable, with a recommendation to use@CheckForNullonly when the calling code must always check for null. It would provide an additional check in SonarQube. And for the other cases, use@Nullable. My fear is that this makes it more complex and as a coder, I’m not 100% sure what it means to ask calling code to always check for null (since there’s no method that always returnnull, there are always conditions (IFs) that would warrant not checking fornullif you know you’re not in the IF that would lead to returning null.
So I have a slight doubt in our ability to use @CheckForNull properly and in an objective way (ie not subjective, ie different depending on the dev).
We could use both
@CheckForNulland@Nullable, with a recommendation to use@CheckForNullonly when the calling code must always check for null. It would provide an additional check in SonarQube. And for the other cases, use@Nullable. My fear is that this makes it more complex and as a coder, I’m not 100% sure what it means to ask calling code to always check for null (since there’s no method that always returnnull, there are always conditions (IFs) that would warrant not checking fornullif you know you’re not in the IF that would lead to returning null.
I’d go for recommending to use always @CheckForNull by default, as it is the safest: most of the time we want to enforce checking for null value if we’re thinking about specifying that the method might be null. We could document that in the rare cases where we don’t need such check we could use @Nullable but frankly I’m not sure I see the point of using an annotation for such case: the javadoc could be enough then.
I’m not sure I see the point of using an annotation for such case: the javadoc could be enough then.
Just to let Sonar know that, yes, we know that method can return null, but it’s OK to not check for null in that specific case.
In the IntelliJ IDEA 2025.2 release notes, I’ve just learned that JSpecify is becoming an industry standard for nullable annotations. Their documentation states that
JSpecify is developed by consensus of major stakeholders in Java static analysis. Our 1.0.0 release is the first tool-neutral, library-neutral artifact for these annotations. (Note:
javax.annotationwas an attempt at this that never reached consensus and was never actually released.)
So I’m not sure adopting javax.annotation is a good idea if the emerging industry standard is JSpecify and “JSR 305 was an attempt that was abandoned before completion” (source).
So I propose that instead of this, we start using JSpecify.
So I propose that instead of this, we start using JSpecify.
It does indeed seem to be the way to go. And I see Sonar is listed as member, so I assume it supports it.
And I see Sonar is listed as member, so I assume it supports it.
I found SONARJAVA-4544, so they support the basic null checks, it’s not fully clear to me if they already support checking null assignments inside @NullMarked code as SONARJAVA-5143 is still open (but the linked issue has been closed).
Re JSpecify I love this part:
- Why standardize the annotations? Because you deserve better than this tragic stackoverflow answer depicts.
<sarcastic mode>
That’s a bit ironic. So to solve the problem of choice, you add a new choice
And then you decree that yours is the standard…
</sarcastic mode>
More seriously, could someone summarize for me what is the problem with javax.annotation? Is it about some feature it doesn’t have?
I don’t know what’s the future for JSpecify but it seems to me that the javax.annotations namespace would be the right one for a Java standard.
Do we know if there are talks in the JCP to eventually make org.jspecify.annotations a first-class citizen, i.e. using the javax namespace? Until it’s there, it’s going to be hard to claim it’s the standard IMO.
Thanks
I don’t know what’s the future for JSpecify but it seems to me that the
javax.annotationsnamespace would be the right one for a Java standard.
Well it’s true that JSR 305 specification (which introduced stuff like `javax.annotation.Nullable`) never been officially released. And the list of members is impressive (including OpenJDK). But it’s indeed surprising to not do that through the JCP if they were able to make all those people be OK with those annotations.
The funny thing is that we are using the Google package of jsr305 as dependency and Google is now the one leading the effort on JSpecify, apparently.
By the way, these days it would probably make more sense to use jakarta.annotation.Nullable from Jakarta Annotations (it’s supposedly been started as JSR 250, but there does not seem to be any mention of Nullable in JSR 250 specifications. It was apparently added later through Add Nullable and NotNull annotations · Issue #89 · jakartaee/common-annotations-api · GitHub ) than the old javax.* versions in any case (but no idea how well this is supported).
(yes, it does seem to be a bit of a mess, even on supposedly standard side)
Sounds like we never reach a conclusion on this discussion, not because we don’t agree on using the annotation, but because we’re hesitating on the one to use. So we should probably take a decision and stick with it.
If I sum up the last contenders are:
- JSpecify
@Nullable @CheckForNull- Javax/Jakarta
@Nullable
JSpecify
@Nullable
From what I could see, JSpecify seems to be winning the battle, and many projects are moving to it. So to me that’s the one that makes the most sense, as the actually still alive standard.
@CheckForNull
Javax@Nullable
I don’t think it really makes any sense to start now using what essentially was a never released proposal and was abandoned a long time ago. Tools like Sonar support it because they try to support all the mess they can find, but it seems quite legacy to me.
Jakarta
@Nullable
This is part of a maintained standard API ( Jakarta Annotations). But the way it was introduced feels a bit messy, compared to jspecify.
From what I could see, JSpecify seems to be winning the battle, and many projects are moving to it. So to me that’s the one that makes the most sense, as the actually still alive standard.
That’s my understanding as well.
+1 for JSpecify
+1 for JSpecify