1343

I'm looking to make my code more readable as well as use tooling like IDE code inspection and/or static code analysis (FindBugs and Sonar) to avoid NullPointerExceptions. Many of the tools seem incompatible with each others' @NotNull/@NonNull/@Nonnull annotation and listing all of them in my code would be terrible to read. Any suggestions of which one is the 'best'? Here is the list of equivalent annotations I've found:

15
  • 262
    apache should invent a "common" annotation and a tool that can convert it to any other annotation. the solution to the problem of too many standards is to invent a new standard. Feb 11, 2011 at 0:15
  • 10
    @irreputable if apache invents a new "common", there would be 56 versions of it, overlapping with other projects. And, it wouldn't be standard anyway (standard != widespread). Better use anything really standard, javax?.* . BTW, there aren't "too many standards" in those examples, I just see 1 or 2.
    – ymajoros
    Oct 27, 2012 at 8:15
  • 8
    javax.annotation.Nonnull does work with findbugs (just tested it), which is a compelling reason for me to use it.
    – Nicolas C
    Jul 18, 2013 at 8:33
  • 26
    If I simply write @NotNull, it refers to com.sun.istack.internal.NotNull. OMG... Mar 6, 2015 at 7:34
  • 4
    @MozartBrocchini - Optionals are useful in cases where you might have previously used NullObjects. They don't really address the same aim as a runtime \@NotNull annotation though, and they introduce tedious unwrapping.
    – Jade
    Jul 19, 2016 at 23:38

26 Answers 26

436
+50

Since JSR 305 (whose goal was to standardize @NonNull and @Nullable) has been dormant for several years, I'm afraid there is no good answer. All we can do is to find a pragmatic solution and mine is as follows:

Syntax

From a purely stylistic standpoint I would like to avoid any reference to IDE, framework or any toolkit except Java itself.

This rules out:

  • android.support.annotation
  • edu.umd.cs.findbugs.annotations
  • org.eclipse.jdt.annotation
  • org.jetbrains.annotations
  • org.checkerframework.checker.nullness.qual
  • lombok.NonNull

Which leaves us with either javax.validation.constraints or javax.annotation. The former comes with JEE. If this is better than javax.annotation, which might come eventually with JSE or never at all, is a matter of debate. I personally prefer javax.annotation because I wouldn't like the JEE dependency.

This leaves us with

javax.annotation

which is also the shortest one.

There is only one syntax which would even be better: java.annotation.Nullable. As other packages graduated from javax to java in the past, the javax.annotation would be a step in the right direction.

Implementation

I was hoping that they all have basically the same trivial implementation, but a detailed analysis showed that this is not true.

First for the similarities:

The @NonNull annotations all have the line

public @interface NonNull {}

except for

  • org.jetbrains.annotations which calls it @NotNull and has a trivial implementation
  • javax.annotation which has a longer implementation
  • javax.validation.constraints which also calls it @NotNull and has an implementation

The @Nullable annotations all have the line

public @interface Nullable {}

except for (again) the org.jetbrains.annotations with their trivial implementation.

For the differences:

A striking one is that

  • javax.annotation
  • javax.validation.constraints
  • org.checkerframework.checker.nullness.qual

all have runtime annotations (@Retention(RUNTIME)), while

  • android.support.annotation
  • edu.umd.cs.findbugs.annotations
  • org.eclipse.jdt.annotation
  • org.jetbrains.annotations

are only compile time (@Retention(CLASS)).

As described in this SO answer the impact of runtime annotations is smaller than one might think, but they have the benefit of enabling tools to do runtime checks in addition to the compile time ones.

Another important difference is where in the code the annotations can be used. There are two different approaches. Some packages use JLS 9.6.4.1 style contexts. The following table gives an overview:

Package FIELD METHOD PARAMETER LOCAL_VARIABLE
android.support.annotation ✔️ ✔️ ✔️
edu.umd.cs.findbugs.annotations ✔️ ✔️ ✔️ ✔️
org.jetbrains.annotation ✔️ ✔️ ✔️ ✔️
lombok ✔️ ✔️ ✔️ ✔️
javax.validation.constraints ✔️ ✔️ ✔️

org.eclipse.jdt.annotation, javax.annotation and org.checkerframework.checker.nullness.qual use the contexts defined in JLS 4.11, which is in my opinion the right way to do it.

This leaves us with

  • javax.annotation
  • org.checkerframework.checker.nullness.qual

in this round.

Code

To help you to compare further details yourself I list the code of every annotation below. To make comparison easier I removed comments, imports and the @Documented annotation. (they all had @Documented except for the classes from the Android package). I reordered the lines and @Target fields and normalized the qualifications.

package android.support.annotation;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER})
public @interface NonNull {}

package edu.umd.cs.findbugs.annotations;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
public @interface NonNull {}

package org.eclipse.jdt.annotation;
@Retention(CLASS)
@Target({ TYPE_USE })
public @interface NonNull {}

package org.jetbrains.annotations;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
public @interface NotNull {String value() default "";}

package javax.annotation;
@TypeQualifier
@Retention(RUNTIME)
public @interface Nonnull {
    When when() default When.ALWAYS;
    static class Checker implements TypeQualifierValidator<Nonnull> {
        public When forConstantValue(Nonnull qualifierqualifierArgument,
                Object value) {
            if (value == null)
                return When.NEVER;
            return When.ALWAYS;
        }
    }
}

package org.checkerframework.checker.nullness.qual;
@Retention(RUNTIME)
@Target({TYPE_USE, TYPE_PARAMETER})
@SubtypeOf(MonotonicNonNull.class)
@ImplicitFor(
    types = {
        TypeKind.PACKAGE,
        TypeKind.INT,
        TypeKind.BOOLEAN,
        TypeKind.CHAR,
        TypeKind.DOUBLE,
        TypeKind.FLOAT,
        TypeKind.LONG,
        TypeKind.SHORT,
        TypeKind.BYTE
    },
    literals = {LiteralKind.STRING}
)
@DefaultQualifierInHierarchy
@DefaultFor({TypeUseLocation.EXCEPTION_PARAMETER})
@DefaultInUncheckedCodeFor({TypeUseLocation.PARAMETER, TypeUseLocation.LOWER_BOUND})
public @interface NonNull {}

For completeness, here are the @Nullable implementations:

package android.support.annotation;
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD})
public @interface Nullable {}

package edu.umd.cs.findbugs.annotations;
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
@Retention(CLASS)
public @interface Nullable {}

package org.eclipse.jdt.annotation;
@Retention(CLASS)
@Target({ TYPE_USE })
public @interface Nullable {}

package org.jetbrains.annotations;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
public @interface Nullable {String value() default "";}

package javax.annotation;
@TypeQualifierNickname
@Nonnull(when = When.UNKNOWN)
@Retention(RUNTIME)
public @interface Nullable {}

package org.checkerframework.checker.nullness.qual;
@Retention(RUNTIME)
@Target({TYPE_USE, TYPE_PARAMETER})
@SubtypeOf({})
@ImplicitFor(
    literals = {LiteralKind.NULL},
    typeNames = {java.lang.Void.class}
)
@DefaultInUncheckedCodeFor({TypeUseLocation.RETURN, TypeUseLocation.UPPER_BOUND})
public @interface Nullable {}

The following two packages have no @Nullable, so I list them separately; Lombok has a pretty boring @NonNull. In javax.validation.constraints the @NonNull is actually a @NotNull and it has a longish implementation.

package lombok;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
public @interface NonNull {}

package javax.validation.constraints;
@Retention(RUNTIME)
@Target({ FIELD, METHOD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Constraint(validatedBy = {})
public @interface NotNull {
    String message() default "{javax.validation.constraints.NotNull.message}";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default {};
    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        NotNull[] value();
    }
}

Support

From my experience, javax.annotation is at least supported by Eclipse and the Checker Framework out of the box.

Summary

My ideal annotation would be the java.annotation syntax with the Checker Framework implementation.

If you don't intend to use the Checker Framework the javax.annotation (JSR-305) is still your best bet for the time being.

If you are willing to buy into the Checker Framework just use their org.checkerframework.checker.nullness.qual.


Sources

  • android.support.annotation from android-5.1.1_r1.jar
  • edu.umd.cs.findbugs.annotations from findbugs-annotations-1.0.0.jar
  • org.eclipse.jdt.annotation from org.eclipse.jdt.annotation_2.1.0.v20160418-1457.jar
  • org.jetbrains.annotations from jetbrains-annotations-13.0.jar
  • javax.annotation from gwt-dev-2.5.1-sources.jar
  • org.checkerframework.checker.nullness.qual from checker-framework-2.1.9.zip
  • lombok from lombok commit f6da35e4c4f3305ecd1b415e2ab1b9ef8a9120b4
  • javax.validation.constraints from validation-api-1.0.0.GA-sources.jar
14
  • 14
    The downside of javax.annotation is that it's a) based on a dead JSR, b) hard to find an artifact that just provides the annotations and is maintained. The one from findbugs is not: search.maven.org/…
    – robinst
    Mar 9, 2017 at 23:51
  • 32
    Another point against javax.annotation is that it causes problems with Java 9 because other modules also provide classes in that package (jax-ws).
    – robinst
    Sep 28, 2017 at 5:52
  • 13
    @kevinarpe: The Findbugs project is dead, and the successor project Spotbugs is removing those annotations: github.com/spotbugs/spotbugs/pull/180
    – robinst
    Nov 27, 2017 at 2:35
  • 16
    JSR 305, which would’ve standardized javax.annotation.NonNull, never completed because its spec lead went AWOL. It had nothing to do with any decision by Oracle. Jul 25, 2018 at 20:55
  • 13
    Another reason not to use jsr305.jar is that it apparently violates the Oracle Java binary license: github.com/google/guava/issues/2960
    – Flow
    Apr 8, 2019 at 10:37
100

I very much like the Checker Framework, which is an implementation of type annotations (JSR-308) which is used to implement defect checkers like a nullness checker. I haven't really tried any others to offer any comparison, but I've been happy with this implementation.

I'm not affiliated with the group that offers the software, but I am a fan.

Four things I like about this system:

  1. It has a defect checkers for nullness (@Nullable), but also has ones for immutability and interning (and others). I use the first one (nullness) and I'm trying to get into using the second one (immutability/IGJ). I'm trying out the third one, but I'm not certain about using it long term yet. I'm not convinced of the general usefulness of the other checkers yet, but its nice to know that the framework itself is a system for implementing a variety of additional annotations and checkers.

  2. The default setting for nullness checking works well: Non-null except locals (NNEL). Basically this means that by default the checker treats everyhing (instance variables, method parameters, generic types, etc) except local variables as if they have a @NonNull type by default. Per the documentation:

    The NNEL default leads to the smallest number of explicit annotations in your code.

    You can set a different default for a class or for a method if NNEL doesn't work for you.

  3. This framework allows you to use with without creating a dependency on the framework by enclosing your annotations in a comment: e.g. /*@Nullable*/. This is nice because you can annotate and check a library or shared code, but still be able to use that library/shared coded in another project that doesn't use the framework. This is a nice feature. I've grown accustom to using it, even though I tend to enable the Checker Framework on all my projects now.

  4. The framework has a way to annotate APIs you use that aren't already annotated for nullness by using stub files.

6
  • 4
    Seems great and I'd like to use it, but cannot. Why GPL? Couldn't it be the LGPL instead?
    – Burkhard
    Dec 4, 2012 at 8:52
  • 15
    According to the FAQ: "The more permissive MIT License applies to code that you might want to include in your own program, such as the annotations."
    – seanf
    Jul 11, 2013 at 3:50
  • 1
    The links are currently broken. But +1 for the advice on using Checker Framework. Oct 21, 2016 at 11:52
  • 1
    It's a pity that the immutability checkers are dropped in latest release. Jan 21, 2017 at 16:54
  • 2
    Checker Framework is also suggested in Oracle Java Tutorials. May 16, 2018 at 8:29
63

I use the IntelliJ one, because I'm mostly concerned with IntelliJ flagging things that might produce a NPE. I agree that it's frustrating not having a standard annotation in the JDK. There's talk of adding it, it might make it into Java 7. In which case there will be one more to choose from!

8
  • 75
    Update: IntelliJ now supports all of the above annotations for code highlighting, so you are not restricted to IntelliJ's annotations any more: blogs.jetbrains.com/idea/2011/03/… Aug 26, 2011 at 0:26
  • 7
    javax.annotation.Nonnull is more widely accepted, isn't it?
    – Martin
    Jul 31, 2013 at 9:35
  • 1
    @DanielAlexiuc But unfortunately, it doesn't use them for its runtime checks, so there is still a benefit to using the JetBrains ones...
    – Hakanai
    Nov 23, 2014 at 22:42
  • 4
    @Trejkaz Since 2016.3 it creates runtime checks for all of those.
    – Karol S
    Mar 6, 2017 at 17:20
  • 1
    Java 17... still looking forward for that hahaha
    – Pwnstar
    Apr 12, 2022 at 14:12
33

According to the Java 7 features list JSR-308 type annotations are deferred to Java 8. JSR-305 annotations are not even mentioned.

There is a bit of info on the state of JSR-305 in an appendix of the latest JSR-308 draft. This includes the observation that JSR-305 annotations seem to be abandoned. The JSR-305 page also shows it as "inactive".

In the mean time, the pragmatic answer is to use the annotation types that are supported by the most widely used tools ... and be prepared to change them if the situation changes.


In fact, JSR-308 does not define any annotation types/classes, and it looks like they think it is out of scope. (And they are right, given the existence of JSR-305).

However, if JSR-308 really looks like making it into Java 8, it wouldn't surprise me if interest in JSR-305 revived. AFAIK, the JSR-305 team hasn't formally abandoned their work. They have just been quiet for 2+ years.

It is interesting that Bill Pugh (the tech lead for JSR-305) is one of the guy behind FindBugs.

2
28

For Android projects you should use android.support.annotation.NonNull and android.support.annotation.Nullable. These and other helpful Android-specific annotations are available in the Support Library.

From http://tools.android.com/tech-docs/support-annotations:

The support library itself has also been annotated with these annotations, so as a user of the support library, Android Studio will already check your code and flag potential problems based on these annotations.

3
  • 3
    It would be useful to provide justification for that recommendation.
    – apricot
    Apr 22, 2015 at 17:10
  • 2
    tools.android.com/tech-docs/support-annotations "The support library itself has also been annotated with these annotations, so as a user of the support library, Android Studio will already check your code and flag potential problems based on these annotations."
    – James Wald
    Apr 22, 2015 at 22:00
  • 3
    BTW Android Studio support jsr305 with javax.annotation.* annotations also
    – CAMOBAP
    Aug 4, 2017 at 17:21
24

Distinguish between static analysis and runtime analysis. Use static analysis for internal stuff, and runtime analysis for the public boundaries of your code.

For things that should not be null:

  • Runtime check: Use "if (x == null) ..." (zero dependency) or @javax.validation.NotNull (with bean validation) or @lombok.NonNull (plain and simple) or guavas Preconditions.checkNotNull(...)

    • Use Optional for method return types (only). Either Java8 or Guava.
  • Static check: Use an @NonNull annotation

  • Where it fits, use @...NonnullByDefault annotations on class or package level. Create these annotations yourself (examples are easy to find).
    • Else, use @...CheckForNull on method returns to avoid NPEs

This should give the best result: warnings in the IDE, errors by Findbugs and checkerframework, meaningful runtime exceptions.

Do not expect static checks to be mature, their naming is not standardized and different libraries and IDEs treat them differently, ignore them. The JSR305 javax.annotations.* classes look like standard, but they are not, and they cause split packages with Java9+.

Some notes explanations:

  • Findbugs/spotbugs/jsr305 annotations with package javax.validation.* clash with other modules in Java9+, also possibly violate Oracle license
  • Spotbugs annotations still depends on jsr305/findbugs annotations at compiletime (at the time of writing https://github.com/spotbugs/spotbugs/issues/421)
  • jetbrains @NotNull name conflicts with @javax.validation.NotNull.
  • jetbrains, eclipse or checkersframework annotations for static checking have the advantage over javax.annotations that they do not clash with other modules in Java9 and higher
  • @javax.annotations.Nullable does not mean to Findbugs/Spotbugs what you (or your IDE) think it means. Findbugs will ignore it (on members). Sad, but true (https://sourceforge.net/p/findbugs/bugs/1181)
  • For static checking outside an IDE, 2 free tools exist: Spotbugs(formerly Findbugs) and checkersframework.
  • The Eclipse library has @NonNullByDefault, jsr305 only has @ParametersAreNonnullByDefault. Those are mere convenience wrappers applying base annotations to everything in a package (or class), you can easily create your own. This can be used on package. This may conflict with generated code (e.g. lombok).
  • Using lombok as an exported dependency should be avoided for libraries that you share with other people, the less transitive dependencies, the better
  • Using Bean validation framework is powerful, but requires high overhead, so that's overkill just to avoid manual null checking.
  • Using Optional for fields and method parameters is controversial (you can find articles about it easily)
  • Android null annotations are part of the Android support library, they come with a whole lot of other classes, and don't play nicely with other annotations/tools

Before Java9, this is my recommendation:

// file: package-info.java
@javax.annotation.ParametersAreNonnullByDefault
package example;


// file: PublicApi
package example;

public interface PublicApi {

    Person createPerson(
        // NonNull by default due to package-info.java above
        String firstname,
        String lastname);
}

// file: PublicApiImpl
public class PublicApiImpl implements PublicApi {
    public Person createPerson(
            // In Impl, handle cases where library users still pass null
            @Nullable String firstname, // Users  might send null
            @Nullable String lastname // Users might send null
            ) {
        if (firstname == null) throw new IllagalArgumentException(...);
        if (lastname == null) throw new IllagalArgumentException(...);
        return doCreatePerson(fistname, lastname, nickname);
    }

    @NonNull // Spotbugs checks that method cannot return null
    private Person doCreatePerson(
             String firstname, // Spotbugs checks null cannot be passed, because package has ParametersAreNonnullByDefault
             String lastname,
             @Nullable String nickname // tell Spotbugs null is ok
             ) {
         return new Person(firstname, lastname, nickname);
    }

    @CheckForNull // Do not use @Nullable here, Spotbugs will ignore it, though IDEs respect it
    private Person getNickname(
         String firstname,
         String lastname) {
         return NICKNAMES.get(firstname + ':' + lastname);
    }
}

Note that there is no way to make Spotbugs raise a warning when a nullable method parameter is dereferenced (at the time of writing, version 3.1 of Spotbugs). Maybe checkerframework can do that.

Sadly these annotations do not distinguish between the cases of a public method of a library with arbitrary callsites, and non-public methods where each callsite can be known. So the double meaning of: "Indicate that null is undesired, but prepare for null being passed nevertheless" is not possible in a single declaration, hence the above example has different annotations for the interface and the implementation.

For cases where the split interface approach is not practical, the following approach is a compromise:

        public Person createPerson(
                @NonNull String firstname,
                @NonNull String lastname
                ) {
            // even though parameters annotated as NonNull, library clients might call with null.
            if (firstname == null) throw new IllagalArgumentException(...);
            if (lastname == null) throw new IllagalArgumentException(...);
            return doCreatePerson(fistname, lastname, nickname);
        }

This helps clients to not pass null (writing correct code), while returning useful errors if they do.

2
  • I found this answer only now, but @tkruse, where did you find this: "Eclipse jdt annotations are not applicable to static method returns and some other cases"? (the first part is not true, the second quite vague :) ). Oct 7, 2019 at 18:54
  • @StephanHerrmann: I cannot remember. I removed the bullet point.
    – tkruse
    Oct 8, 2019 at 1:34
20

If anyone is just looking for the IntelliJ classes: you can get them from the maven repository with

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations</artifactId>
    <version>15.0</version>
</dependency> 
4
  • This is the one that causes Intellij to throw up warnings, yep.
    – Ali
    Apr 1, 2016 at 9:48
  • Current version (as of 05/2017) is 15.0
    – BamaPookie
    May 16, 2017 at 17:53
  • Your right. I've updated the version. Even if I guess it hasn't changed much. May 17, 2017 at 19:54
  • Keep in mind that the JetBrains annotations are not retained for runtime, so Guice @Nullable support for example does not work with it. Nov 23, 2017 at 9:46
19

JSR305 and FindBugs are authored by the same person. Both are poorly maintained but are as standard as it gets and are supported by all major IDEs. The good news is that they work well as-is.

Here is how to apply @Nonnull to all classes, methods and fields by default. See https://stackoverflow.com/a/13319541/14731 and https://stackoverflow.com/a/9256595/14731

  1. Define @NotNullByDefault
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;


    /**
     * This annotation can be applied to a package, class or method to indicate that the class fields,
     * method return types and parameters in that element are not null by default unless there is: <ul>
     * <li>An explicit nullness annotation <li>The method overrides a method in a superclass (in which
     * case the annotation of the corresponding parameter in the superclass applies) <li> there is a
     * default parameter annotation applied to a more tightly nested element. </ul>
     * <p/>
     * @see https://stackoverflow.com/a/9256595/14731
     */
    @Documented
    @Nonnull
    @TypeQualifierDefault(
    {
        ElementType.ANNOTATION_TYPE,
        ElementType.CONSTRUCTOR,
        ElementType.FIELD,
        ElementType.LOCAL_VARIABLE,
        ElementType.METHOD,
        ElementType.PACKAGE,
        ElementType.PARAMETER,
        ElementType.TYPE
    })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NotNullByDefault
    {
    }

2. Add the annotation to each package: package-info.java

@NotNullByDefault
package com.example.foo;

UPDATE: As of December 12th, 2012 JSR 305 is listed as "Dormant". According to the documentation:

A JSR that was voted as "dormant" by the Executive Committee, or one that has reached the end of its natural lifespan.

It looks like JSR 308 is making it into JDK 8 and although the JSR does not define @NotNull, the accompanying Checkers Framework does. At the time of this writing, the Maven plugin is unusable due to this bug: https://github.com/typetools/checker-framework/issues/183

3
  • 2
    The showstopper issue for maven is fixed. So this should be an option again. Jul 24, 2013 at 12:12
  • I use FindBugs via Maven, nothing is done by my IDE, this avoids IDE specific annotations, what would you recommend ? Jul 25, 2016 at 12:52
  • @ChristopheRoussy Your question is IDE-specific. Please open a separate question.
    – Gili
    Jul 26, 2016 at 14:52
17

JSpecify will be the way to go (when it's ready enough). In fact: their presentation actively links to this very question and specifies that their goal is for it to finally have a good answer.

It has major participants like Android, Guava and Kotlin.

3
  • 1
    Now? Their repo and site doesn't give the impression that it's usable yet. There seems to be a v0.2.0 on maven, but nothing in the repo.
    – gix
    Aug 25, 2021 at 13:00
  • 1
    You can use org.jspecify:jspecify:0.2.0 and that actually has 2 annotations. See github.com/jspecify/jspecify/releases Since it's still a beta, they stress to not use it in libraries yet.
    – Cristan
    Oct 5, 2021 at 12:59
  • 2
    Meanwhile v0.3.0 is released with a good user guide: jspecify.dev/docs/user-guide. For the "pro" feature of @NullMarked IntelliJ IDE support is not fully there, but it will be fixed: youtrack.jetbrains.com/issue/IDEA-323691/… (please vote up)
    – koppor
    Aug 29, 2023 at 10:37
12

Eclipse has also its own annotations.

org.eclipse.jdt.annotation.NonNull

See at http://wiki.eclipse.org/JDT_Core/Null_Analysis for details.

1
  • It looks like this is going to be integrated from Eclipse 3.8 (Juno) which will bring Eclipse in-line with IntelliJ in this regard. Also it should allow you to configure your own Null annotations (e.g. javax.annotation.Nonnull) and has an option to have NotNull the default. Jun 15, 2012 at 12:08
11

Just pointing out that the Java Validation API (javax.validation.constraints.*) doesn't come with a @Nullable annotation, which is very valuable in a static analysis context. It makes sense for runtime bean validation as this is the default for any non-primitive field in Java (i.e. nothing to validate/enforce). For the purposes stated that should weigh towards the alternatives.

9

newer projects should probably use jakarta.annotation-api (jakarta.annotation package).
It is linked from now read-only javax.annotation repo and fits into the new jakarta ecosystem that aims to free the community from all the javax related headaches.

1
  • 3
    Jakarta annotation API is the future: jakarta.annotation.Nonnull & jakarta.annotation.Nullable. They are standard & with generic semantic. Good bye Javax Validation API annotations!
    – gavenkoa
    Apr 25, 2023 at 21:29
8

There are already too many answers here, but (a) it's 2019, and there's still no "standard" Nullable and (b) no other answer references Kotlin.

The reference to Kotlin is important, because Kotlin is 100% interoperable with Java and it has a core Null Safety feature. When calling Java libraries, it can take advantage of those annotations to let Kotlin tools know if a Java API can accept or return null.

As far as I know, the only Nullable packages compatible with Kotlin are org.jetbrains.annotations and android.support.annotation (now androidx.annotation). The latter is only compatible with Android so it can't be used in non-Android JVM/Java/Kotlin projects. However, the JetBrains package works everywhere.

So if you develop Java packages that should also work in Android and Kotlin (and be supported by Android Studio and IntelliJ), your best choice is probably the JetBrains package.

Maven:

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations-java5</artifactId>
    <version>15.0</version>
</dependency>

Gradle:

implementation 'org.jetbrains:annotations-java5:15.0'
4
7

Unfortunately, JSR 308 will not add more values than this project local Not Null suggestion here

Java 8 will not come with a single default annotation or its own Checker framework. Similar to Find-bugs or JSR 305, this JSR is poorly maintained by a small bunch of mostly academic teams.

No commercial power behind it, thus JSR 308 launches EDR 3 (Early Draft Review at JCP) NOW, while Java 8 is supposed to ship in less than 6 months:-O Similar to 310 btw. but unlike 308 Oracle has taken charge of that now away from its founders to minimize harm it'll do to the Java Platform.

Every project, vendor and academic class like the ones behind the Checker Framework and JSR 308 will create its own proprietary checker annotation.

Making source code incompatible for years to come, until a few popular compromises could be found and maybe added to Java 9 or 10, or via frameworks like Apache Commons or Google Guava;-)

7

Android

This answer is Android specific. Android has support package called support-annotations. This provides dozens of Android specific annotations and also provides common ones like NonNull, Nullable etc.

To add support-annotations package, add the following dependency in your build.gradle:

compile 'com.android.support:support-annotations:23.1.1'

and then use:

import android.support.annotation.NonNull;

void foobar(@NonNull Foo bar) {}
6

If you are working on a big project, you may be better of creating your own @Nullable and/or @NotNull annotations.

For example:

@java.lang.annotation.Documented
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
@java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD,
                              java.lang.annotation.ElementType.METHOD,    
                              java.lang.annotation.ElementType.PARAMETER,
                              java.lang.annotation.ElementType.LOCAL_VARIABLE})
public @interface Nullable 
{
}

If you use the correct retention policy, then the annotations won't be available at runtime. From that point of view, it is just an internal thing.

Even though this is not a strict science, I think it makes most sense to use an internal class for it.

  • It is an internal thing. (no functional or technical impact)
  • With many many many usages.
  • IDE's like IntelliJ support custom @Nullable/@NotNull annotations.
  • Most frameworks prefer to use their own internal version as well.

Additional Questions (see comments):

How to configure this in IntelliJ ?

Click the "police officer" in the lower right corner of the IntelliJ status bar. And click "Configure inspections" in the popup. Next ... configure annotations

3
  • 1
    I tried your advice, but idea tell nothing about void test(@NonNull String s) {} called by test(null); Mar 3, 2017 at 11:31
  • 3
    @user1244932 Do you mean IntelliJ IDEA? You can configure the nullability annotations it uses for static analysis. I don't exactly know where, but one place to define them in is in "File > Settings > Build, Execution, Deployment > Compiler" and there in is a button "Configure annotations...".
    – Adowrath
    Mar 23, 2017 at 17:23
  • @user1244932 see screenshot if you are still looking for this.
    – bvdb
    Oct 27, 2017 at 10:53
6

There is another way to do this in Java 8. I am doing 2 things to accomplish what I needed:

  1. Making nullable fields explicit with types by wrapping nullable fields with java.util.Optional
  2. Checking that all non nullable fields are not null at construction time with java.util.Objects.requireNonNull

Example:

Edit: Disregard this 1st example, I'm just leaving here as context of the comments conversation. Skip to recommended option after this (2nd code block).

    import static java.util.Objects.requireNonNull;

    public class Role {

      private final UUID guid;
      private final String domain;
      private final String name;
      private final Optional<String> description;

      public Role(UUID guid, String domain, String name, Optional<String> description) {
        this.guid = requireNonNull(guid);
        this.domain = requireNonNull(domain);
        this.name = requireNonNull(name);
        this.description = requireNonNull(description);
      }
   }

So my question is, do we even need to annotate when using java 8?

Edit: I found out later that some consider a bad practice to use Optional in arguments, there is a good discussion with pros and cons here Why should Java 8's Optional not be used in arguments

Recommended option given that it is not best practice to use Optional in arguments, we need 2 constructors:

public class Role {
      
      // Required fields, will not be null (unless using reflection) 
      private final UUID guid;
      private final String domain;
      private final String name;
      // Optional field, not null but can be empty
      private final Optional<String> description;

  //Non null description
  public Role(UUID guid, String domain, String name, String description) {
        this.guid = requireNonNull(guid);
        this.domain = requireNonNull(domain);
        this.name = requireNonNull(name);

        // description will never be null
        requireNonNull(description);

        // but wrapped with an Optional
        this.description = Optional.of(description);
      }

  // Null description is assigned to Optional.empty
  public Role(UUID guid, String domain, String name) {
        this.guid = requireNonNull(guid);
        this.domain = requireNonNull(domain);
        this.name = requireNonNull(name);
        this.description = Optional.empty();
      }
  //Note that this accessor is not a getter.
  //I decided not to use the "get" suffix to distinguish from "normal" getters 
  public Optional<String> description(){ return description;} 
 }
11
  • 1
    I'd say you do still need the @NotNull annotation for all 4 formal parameters so that static analysis checkers know your intention that none should be null. There's nothing in the Java language yet that enforces that. You should also be checking that description is not null if you're programming defensively.
    – jaxzin
    May 11, 2016 at 22:21
  • 4
    I can still write this code: new Role(null,null,null,null);. With the annotations my IDE and static analysis will warn that null can't be passed into those parameters. Without it I don't find out until I run the code. That's the value of the annotations.
    – jaxzin
    May 27, 2016 at 21:00
  • 2
    I'm also in environments where developers can use any IDE or text editor they prefer, its not mutually-exclusive. We then also integrate the maven-pmd-plugin and/or SonarQube into the build process to encourage and highlight, and even gate, code quality issues pre-merge, for example on pull requests.
    – jaxzin
    Jun 1, 2016 at 16:41
  • 3
    Optional is not meant to be used as a method argument or private field. See for example: stuartmarks.wordpress.com/2016/09/27/vjug24-session-on-optional
    – assylias
    Sep 29, 2016 at 12:38
  • 1
    @assylias yes, I found that out later, they say it is not recommended because it won't buy us anything, I can definitely understand their rational. In this case I put here, one could make the argument description not null and client code could pass an empty String, but in many cases it could be handy to distinguish between and empty String and not having a value. Thanks for your comment. I will update the answer. Oct 3, 2016 at 16:04
5

While waiting for this to be sorted out upstream (Java 8?), you could also just define your own project-local @NotNull and @Nullable annotations. This can be useful also in case you're working with Java SE, where javax.validation.constraints isn't available by default.

import java.lang.annotation.*;

/**
 * Designates that a field, return value, argument, or variable is
 * guaranteed to be non-null.
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@Documented
@Retention(RetentionPolicy.CLASS)
public @interface NotNull {}

/**
 * Designates that a field, return value, argument, or variable may be null.
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@Documented
@Retention(RetentionPolicy.CLASS)
public @interface Nullable {}

This would admittedly largely be for decorative or future-proofing purposes, since the above obviously doesn't in and of itself add any support for the static analysis of these annotations.

5

If you are building your application using Spring Framework I would suggest using javax.validation.constraints.NotNull comming from Beans Validation packaged in following dependency:

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.1.0.Final</version>
    </dependency>

The main advantage of this annotation is that Spring provides support for both method parameters and class fields annotated with javax.validation.constraints.NotNull. All you need to do to enable support is:

  1. supply the api jar for beans validation and jar with implementation of validator of jsr-303/jsr-349 annotations (which comes with Hibernate Validator 5.x dependency):

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.1.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.4.1.Final</version>
    </dependency>
    
  2. provide MethodValidationPostProcessor to spring's context

      @Configuration
      @ValidationConfig
      public class ValidationConfig implements MyService {
    
            @Bean
            public MethodValidationPostProcessor providePostProcessor() {
                  return new MethodValidationPostProcessor()
            }
      }
    
  3. finally you annotate your classes with Spring's org.springframework.validation.annotation.Validated and validation will be automatically handled by Spring.

Example:

@Service
@Validated
public class MyServiceImpl implements MyService {

  @Override
  public Something doSomething(@NotNull String myParameter) {
        // No need to do something like assert myParameter != null  
  }
}

When you try calling method doSomething and pass null as the parameter value, spring (by means of HibernateValidator) will throw ConstraintViolationException. No need for manuall work here.

You can also validate return values.

Another important benefit of javax.validation.constraints.NotNull comming for Beans Validation Framework is that at the moment it is still developed and new features are planned for new version 2.0.

What about @Nullable? There is nothing like that in Beans Validation 1.1. Well, I could arguee that if you decide to use @NotNull than everything which is NOT annotated with @NonNull is effectively "nullable", so the @Nullable annotation is useless.

2
  • 2
    Please do not use it. It is used for runtime validation, NOT static code analysis. See justsomejavaguy.blogspot.com/2011/08/… for details. Source: DELETED answer with 219 votes by @luis.espinal.
    – koppor
    Mar 29, 2020 at 13:09
  • @koppor: I disagree. If this is not intended for usage why would Spring handle it at runtime. Also Beans validation framework allows to create annotations purely for runtime analysis, as it allows to access Context object (currently annotated/validated instancje) at runtime.
    – walkeros
    Apr 6, 2020 at 6:48
5

One of the nice things about IntelliJ is that you don't need to use their annotations. You can write your own, or you can use those of whatever other tool you like. You're not even limited to a single type. If you're using two libraries that use different @NotNull annotations, you can tell IntelliJ to use both of them. To do this, go to "Configure Inspections", click on the "Constant Conditions & Exceptions" inspection, and hit the "Configure inspections" button. I use the Nullness Checker wherever I can, so I set up IntelliJ to use those annotations, but you can make it work with whatever other tool you want. (I have no opinion on the other tools because I've been using IntelliJ's inspections for years, and I love them.)

4

If you're developing for android, you're somewhat tied to Eclipse (edit: at time of writing, not anymore), which has its own annotations. It's included in Eclipse 3.8+ (Juno), but disabled by default.

You can enable it at Preferences > Java > Compiler > Errors/Warnings > Null analysis (collapsable section at the bottom).

Check "Enable annotation-based null analysis"

http://wiki.eclipse.org/JDT_Core/Null_Analysis#Usage has recommendations on settings. However, if you have external projects in your workspace (like the facebook SDK), they may not satisfy those recommendations, and you probably don't want to fix them with each SDK update ;-)

I use:

  1. Null pointer access: Error
  2. Violation of null specification: Error (linked to point #1)
  3. Potential null pointer access: Warning (otherwise facebook SDK would have warnings)
  4. Conflict between null annotations and null inference: Warning (linked to point #3)
6
  • 5
    tied to Eclipse? Not true.
    – dcow
    Aug 12, 2013 at 23:41
  • 1
    @DavidCowden IntelliJ IDEA with support for Android dev`ing, I think, was available some time before AndroidStudio was introcuded. Oct 13, 2013 at 19:04
  • @MārtiņšBriedis yes, that is true. I think you meant @chaqke.
    – dcow
    Oct 15, 2013 at 18:48
  • it's worth noting that android and intellij have separate annotations, and will likely remain that way until java includes official annotations. these are instructions for using eclipse's annotations with eclipse.
    – chaqke
    Oct 15, 2013 at 22:41
  • It has never been tied to Eclipse. You can use any IDE you want to.
    – DennisK
    Jan 4, 2014 at 11:28
4

A bit more details on why to choose jspecify eventually:

jspecify, is being created by a group led by Google:

EISOP Team, Google, JetBrains, Meta , Microsoft , Oracle ,PMD Team , Sonar , Square , Uber , VMware .

They aim to create a tool-independent nullness annotation standard.

They list the reasons to (eventually) use it in their FAQ

  • consensus
  • precisely defined
  • less strict than the awesome checker framework (complex, hard to migrate, false positives)
  • not tool-specific
3

If you are using Spring 5.x / SpringBoot 2.x you should definitely use the Spring annotations (org.springframework.lang), as they provide you a default package-wide null check with the annotations @NonNullFields and @NonNullApi. You will not even have a clash with other NotNull/NonNull annotations from other dependencies, as you are using @NonNullFields/@NonNullApi. The annotations must be used in a file called package-info.java which is placed in the root directory of the package:

@NonNullFields
@NonNullApi
package org.company.test;

To exclude certain fields, parameters, or return values from the null check, just explicitly use the @Nullable annotation. Instead of using @NonNullFields/@NonNullApi you could also set @NonNull everywhere, but probably it is better to activate null checks with @NonNullFields/@NonNullApi by default and only do specific exceptions with @Nullable.

The IDE (Intellij) will highlight code that violates the null conditions. If set up correctly, every developer can assume that fields, parameters and return values must be not null, unless there is a @Nullable annotation. For more information check out this article.

1
  • Thank you for the info. I have added these to multiple packages however I don't see any warnings when I pass nulls. Oct 14, 2023 at 20:39
2

Doesn't sun have their own now? What's this:
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-com.sun/istack/com.sun.istack.internal.htm

This seems to be packaged with all the versions of Java I've used within the last few years.

Edit: As mentioned in the comments below, you probably don't want to use these. In that case, my vote is for the IntelliJ jetbrains annotations!

3
  • 11
    I've no idea what it is, but the package name should be a BIG CLUE that it is NOT intended for general use.
    – Stephen C
    Feb 10, 2011 at 22:44
  • 3
    One usually refrains from using classes in the com.sun namespace as they are internal; not meant for direct usage; and w/o no guarantees as for their future availability or behavior. One has to have a really solid case to directly use a com.sun artifact. Feb 10, 2011 at 22:46
  • plus something displayed in such poor HTML format (on Java2s.com to top it off) should give you some red flags :) Feb 10, 2011 at 22:47
2

Spring 5 has @NonNullApi at the package level. This seems like a convenient choice for a project that already has Spring dependencies. All fields, parameters and return values default to @NonNull and @Nullable can be applied in the few places that differ.

File package-info.java:

@org.springframework.lang.NonNullApi
package com.acme;

https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.nullability.annotations

1

Another option is the annotations provided with ANTLR 4. Following Pull Request #434, the artifact containing the @NotNull and @Nullable annotations includes an annotation processor that produces compile-time errors and/or warnings in the event one of these attributes is misused (for example, if both are applied to the same item, or if @Nullable is applied to item with a primitive type). The annotation processor provides additional assurance during the software development process that the information conveyed by the application of these annotations is accurate, including in cases of method inheritance.

Not the answer you're looking for? Browse other questions tagged or ask your own question.