1119

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:

mancze
  • 529
  • 4
  • 18
jaxzin
  • 11,591
  • 4
  • 16
  • 19
  • 215
    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. – irreputable Feb 11 '11 at 00:15
  • @NotNull within idea also does runtime checking (At least in v10.5) – krosenvold Aug 10 '11 at 09:04
  • 6
    @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 '12 at 08:15
  • 7
    javax.annotation.Nonnull does work with findbugs (just tested it), which is a compelling reason for me to use it. – Nicolas C Jul 18 '13 at 08:33
  • 2
    @irreputable there was nothing wrong with inventing a logging facade - the implementation was just broken badly enough to prompt the creation of slf4j which - in my opinion- got it right. – Thorbjørn Ravn Andersen Oct 24 '13 at 11:35
  • 22
    If I simply write @NotNull, it refers to `com.sun.istack.internal.NotNull`. OMG... – Thomas Weller Mar 06 '15 at 07:34
  • 1
    Java 8 introduced Optional as a way to avoid Nulls, I'd like to hear from others, to see whether they think this is still an issue when using Java 8. See my answer below. – Mozart Brocchini May 11 '16 at 23:09
  • 1
    @ymajoros that was a joke, see http://xkcd.com/927/ – steffen May 23 '16 at 13:16
  • 1
    @steffen Sure, got it... But Apache didn't, and a lot of people keep using the s-word for any random library. ;-) – ymajoros May 23 '16 at 14:16
  • 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. – Dave Jul 19 '16 at 23:38
  • 1
    FWIW I would go with the javax.validation annotation.You avoid the possibility of kitchen-sink transitive dependencies; it is part of an "actual" standard so it won't disappear when a package maintainer moves on; it has runtime retention so it serves the most useful purpose of a NotNull declaration - enforcement at validation time; it can be inspected at compile time or in the verify phase of a maven build - you just need to add support to your chosen analysis plugin. – Dave Jul 19 '16 at 23:43
  • @Dave, I have idea what you mean by `NullObjects`, and no I was not suggesting that would address the same as annotation, I honestly don't like the idea of using annotations to give a hint for static analysis, but I guess everybody here likes them, so I will stop barking at the wrong tree. – Mozart Brocchini Aug 04 '16 at 21:21
  • @MozartBrocchini - I would not advocate using the annotation _only_ as an aid to static analysis. As I said in the following comment, its most useful purpose is in actually validating values passed at runtime. NullObject is a design pattern where "non-existence" is represented by a class instance that no-ops (or some other function as desired) calls that would otherwise be protected by null checks. As an example of a similar approach you would return empty collections rather than null where a collection was expected as the return type for some method. – Dave Aug 05 '16 at 00:55
  • "javax.validation.constraints.NotNull - Created for runtime validation, not static analysis.". I can't find a hard quote on this and it seems to work just fine in IntelliJ and Sonar. Why is this a bad choice? – Benny Bottema Jul 17 '18 at 08:59
  • @BennyBottema Describing why it exists doesn't mean there is an opinion here that its a bad choice. It has an '@Retention' of RUNTIME, so that it can be used to validate constraints in a runtime environment: https://stackoverflow.com/questions/3107970/how-do-different-retention-policies-affect-my-annotations – jaxzin Sep 27 '18 at 19:41
  • 1
    There is an ongoing effort to unify this mess. See this comment and thread: https://github.com/google/guava/issues/2960#issuecomment-573876214 – coffee_machine Mar 28 '20 at 16:26

22 Answers22

285

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 @Nullableannotations 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:


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

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
Ludwig Weinzierl
  • 13,860
  • 9
  • 43
  • 46
  • 7
    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: https://search.maven.org/#search|gav|1|g%3A%22com.google.code.findbugs%22%20AND%20a%3A%22jsr305%22 – robinst Mar 09 '17 at 23:51
  • 22
    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 '17 at 05:52
  • @robinst: `com.google.code.findbugs:jsr305` was updated just after your comment (Mar 2017). Can you be more specific about what exactly needs to be maintained or is not maintained in the Google package? – kevinarpe Nov 25 '17 at 10:51
  • 10
    @kevinarpe: The Findbugs project is dead, and the successor project Spotbugs is removing those annotations: https://github.com/spotbugs/spotbugs/pull/180 – robinst Nov 27 '17 at 02:35
  • 6
    [JSR 305](https://jcp.org/en/jsr/detail?id=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. – Mark Reinhold Jul 25 '18 at 20:55
  • 1
    There's a gotcha on the FindBugs `Nullable`: I do not think it means what you think it means. It does not mean "this field may contain null and you need to check for it." It instead means, "treat this field as if it were not annotated at all." The FindBugs annotation that says "check for null" is instead named `@CheckForNull`. – ThrawnCA Nov 15 '18 at 22:52
  • 1
    Sadly javax.annotation.Nonnull is not fully supported by eclipse because as long as it does not explicitly specify a target it cannot be applied at any position. For example you cannot define List which would tell the eclipse null checker that the list does not contain any null values. – cornz Dec 14 '18 at 19:57
  • 6
    Another reason not to use jsr305.jar is that it apparently violates the Oracle Java binary license: https://github.com/google/guava/issues/2960 – Flow Apr 08 '19 at 10:37
  • 2
    Nowadays the Checker framework seems widely supported. Can you nuance the practical difference between javax annotations and checker.qual? For example, wouldn't Spotbugs work with checker.qual annotations [now](https://github.com/spotbugs/spotbugs/issues/523)? – Benny Bottema Jun 12 '19 at 18:45
  • Edited the answer to clarify the status of JSR 305, along the lines of the comment from Mark Reinhold (Java Platform Architect) above. – Stuart Marks Jul 31 '19 at 17:14
  • about java 9 problems, see [this](https://stackoverflow.com/questions/37598775/jsr-305-annotations-replacement-for-java-9/37911663#37911663) - I read it so that it should no longer be a problem – eis Sep 16 '19 at 06:05
  • I am confused about why JCP do not push the working... – fjjiaboming Oct 03 '20 at 07:23
96

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.

mernst
  • 6,276
  • 26
  • 41
Bert F
  • 78,021
  • 11
  • 97
  • 121
  • 3
    Seems great and I'd like to use it, but cannot. Why GPL? Couldn't it be the LGPL instead? – Burkhard Dec 04 '12 at 08:52
  • 13
    According to the [FAQ](http://types.cs.washington.edu/checker-framework/current/checkers-manual.html#credits): "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 '13 at 03:50
  • 1
    The links are currently broken. But +1 for the advice on using Checker Framework. – Paul Wagland Oct 21 '16 at 11:52
  • 1
    It's a pity that the immutability checkers are dropped in latest release. – Franklin Yu Jan 21 '17 at 16:54
  • 1
    Checker Framework is also suggested in [Oracle Java Tutorials](https://docs.oracle.com/javase/tutorial/java/annotations/type_annotations.html). – Quazi Irfan May 16 '18 at 08:29
  • Seems like the only linter that just works for JDK11 & non-Android. I also tried findbugs( no JDK11) & spotbugs( hard to setup on JDK11 ) & NullAway ( must use errorprone, hard to setup) & Infer ( no jsr305/308 ). – jchnxu May 16 '20 at 14:02
  • 1
    this should be the correct answer. – Dexter Legaspi Mar 13 '21 at 18:37
58

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!

Sam Barnum
  • 9,932
  • 3
  • 48
  • 57
  • 71
    Update: IntelliJ now supports all of the above annotations for code highlighting, so you are not restricted to IntelliJ's annotations any more: http://blogs.jetbrains.com/idea/2011/03/more-flexible-and-configurable-nullublenotnull-annotations/ – Daniel Alexiuc Aug 26 '11 at 00:26
  • 5
    `javax.annotation.Nonnull` is more widely accepted, isn't it? – Martin Jul 31 '13 at 09: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... – Trejkaz Nov 23 '14 at 22:42
  • 4
    @Trejkaz Since 2016.3 it creates runtime checks for all of those. – Karol S Mar 06 '17 at 17:20
32

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.

mernst
  • 6,276
  • 26
  • 41
Stephen C
  • 632,615
  • 86
  • 730
  • 1,096
  • 4
    @pst - the current schedule is for Java 8 to go to general release in September 2013 - http://www.infoq.com/news/2012/04/jdk-8-milestone-release-dates – Stephen C Jul 19 '12 at 00:30
  • 2
    That has slipped to March 2014 now - http://openjdk.java.net/projects/jdk8/. JSR 308 is included in build M7 (look in "104 - Annotations on Java Types"). – Stephen C May 10 '13 at 10:53
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.

James Wald
  • 13,196
  • 5
  • 48
  • 63
  • 3
    It would be useful to provide justification for that recommendation. – apricot Apr 22 '15 at 17:10
  • 2
    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." – James Wald Apr 22 '15 at 22:00
  • 3
    BTW Android Studio support jsr305 with `javax.annotation.*` annotations also – CAMOBAP Aug 04 '17 at 17:21
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> 
Bruno Eberhard
  • 1,528
  • 15
  • 21
18

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

Community
  • 1
  • 1
Gili
  • 76,473
  • 85
  • 341
  • 624
18

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.

tkruse
  • 8,363
  • 5
  • 43
  • 70
  • 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 :) ). – Stephan Herrmann Oct 07 '19 at 18:54
  • @StephanHerrmann: I cannot remember. I removed the bullet point. – tkruse Oct 08 '19 at 01:34
12

Eclipse has also its own annotations.

org.eclipse.jdt.annotation.NonNull

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

Manos Nikolaidis
  • 18,967
  • 11
  • 60
  • 72
Horcrux7
  • 21,867
  • 21
  • 85
  • 134
  • 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. – Motti Strom Jun 15 '12 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.

Ophir Radnitz
  • 1,553
  • 2
  • 19
  • 18
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;-)

Baby Groot
  • 4,609
  • 39
  • 50
  • 67
Werner Keil
  • 117
  • 1
  • 2
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) {}
Shubham Chaudhary
  • 36,933
  • 9
  • 67
  • 78
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.

Community
  • 1
  • 1
Arto Bendiken
  • 2,293
  • 1
  • 22
  • 26
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)
chaqke
  • 1,297
  • 15
  • 22
  • 4
    *tied to Eclipse?* Not true. – dcow Aug 12 '13 at 23:41
  • 1
    @DavidCowden IntelliJ IDEA with support for Android dev`ing, I think, was available some time before AndroidStudio was introcuded. – Mārtiņš Briedis Oct 13 '13 at 19:04
  • @MārtiņšBriedis yes, that is true. I think you meant `@chaqke`. – dcow Oct 15 '13 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 '13 at 22:41
  • It has never been tied to Eclipse. You can use any IDE you want to. – DennisK Jan 04 '14 at 11:28
  • Java does not have its own annotations until Java 8 ( http://stackoverflow.com/a/4963420/857125 ). Until then, Eclipse and IntelliJ have their own implementations that are not compatible with each other. This answer is pertinent to Eclipse; and IntelliJ explains how to use theirs here: http://www.jetbrains.com/idea/documentation/howto.html , and of course you can use whatever tools you want :-) – chaqke Jan 21 '14 at 01:12
4

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:

  //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();
      }
Mozart Brocchini
  • 312
  • 2
  • 10
  • 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 '16 at 22:21
  • @jazin since it's not possible to create an instance where guid==null || domain==null || name==null what would be the value of having the static analysis tool to perform those checks ? Thanks for pointing the problem with description above, I edited and fixed: `this.description = checkNotNull(description);` – Mozart Brocchini May 19 '16 at 18:58
  • 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 '16 at 21:00
  • @jaxzin, I see your use case and how it is useful for you. But this would never work in my environment where developers are free to use any IDE they like, we have mostly Eclipse and Intellij, but there are a few developers who only code in VI. So my way fits my workflow much better, because even if you use VI to edit the code, you will not be able to write any code that will only eventually break in a non deterministic way later, and thus having a potential for creating bugs that are very hard to track. – Mozart Brocchini May 31 '16 at 16:07
  • 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 01 '16 at 16:41
  • Just as @jaxzin told. These annotations should be used by a build plugin or pre-commit hook to fail as fast as possible. Using your method will move that checking into runtime which is very bad. – lschuetze Jun 25 '16 at 20:21
  • @Ischuetze, thank you for your comment, I also like failing fast. Question: isn't failing at run time faster than failing only after you commit ? I mean, shouldn't engineers run their code before they commit ? Also should one run tests before committing ? If the code is ever going to be used anywhere, it will fail really fast, fail at constructor time, if the code is not going to ever be used the static analysis tools should warn that, example: Intellij does warn about unused code. – Mozart Brocchini Jun 26 '16 at 21:06
  • @MozartBrocchini I think you're assuming every developer always does the right thing. Trust but verify is a much safer approach for everyone. Trust they'll run the the app and tests locally, but verify they have and nothing is broken during the build. – jaxzin Jun 27 '16 at 16:53
  • @jaxzin I am writing libraries that enforce the client developers to do the right thing. A developer cannot do the wrong thing when he/she tries to use the `Role` class above. – Mozart Brocchini Jul 08 '16 at 16:18
  • 2
    Optional is not meant to be used as a method argument or private field. See for example: https://stuartmarks.wordpress.com/2016/09/27/vjug24-session-on-optional/ – assylias Sep 29 '16 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. – Mozart Brocchini Oct 03 '16 at 16:04
4

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

Community
  • 1
  • 1
bvdb
  • 15,306
  • 3
  • 82
  • 95
  • 1
    I tried your advice, but `idea` tell nothing about `void test(@NonNull String s) {}` called by `test(null);` – user1244932 Mar 03 '17 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 '17 at 17:23
  • @user1244932 see screenshot if you are still looking for this. – bvdb Oct 27 '17 at 10:53
4

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.

walkeros
  • 3,745
  • 4
  • 26
  • 38
  • 2
    Please do not use it. It is used for runtime validation, NOT static code analysis. See http://justsomejavaguy.blogspot.com/2011/08/nullable-null-notnull-notnull-nonnull.html for details. Source: DELETED answer with 219 votes by @luis.espinal. – koppor Mar 29 '20 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 06 '20 at 06:48
4

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'
noamtm
  • 10,618
  • 13
  • 60
  • 93
  • 3
    Hmm, this says otherwise: https://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations – skagedal Oct 12 '19 at 21:01
  • To be specific, [Kotlin also documents support for](https://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations) `javax.annotation`, `edu.umd.cs.findbugs.annotations`, `org.eclipse.jdt.annotation` and `lombok.NonNull`, as well as [the implentation also including](https://github.com/JetBrains/kotlin/blob/5ab822be36d34b22598f4bae4edeeb9685f76e6f/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt) `org.checkerframework` and `io.reactivex.annotations`. – Joe Oct 04 '20 at 12:56
3

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.)

MiguelMunoz
  • 3,787
  • 1
  • 25
  • 31
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!

Nate W.
  • 8,631
  • 6
  • 38
  • 65
  • 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 '11 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. – luis.espinal Feb 10 '11 at 22:46
  • plus something displayed in such poor HTML format (on Java2s.com to top it off) should give you some red flags :) – luis.espinal Feb 10 '11 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

ken jarrad
  • 37
  • 4
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.

Sam Harwell
  • 92,171
  • 18
  • 189
  • 263