Home » Java » Which @NotNull Java annotation should I use?

Which @NotNull Java annotation should I use?

Posted by: admin November 2, 2017 Leave a comment

Questions:

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:

  • javax.validation.constraints.NotNull
    Created for runtime validation, not static analysis.
    documentation

  • edu.umd.cs.findbugs.annotations.NonNull
    Used by Findbugs static analysis and therefore Sonar (now Sonarqube)
    documentation

  • javax.annotation.Nonnull
    This might work with Findbugs too, but JSR-305 is inactive. (See also: What is the status of JSR 305?)
    source

  • org.jetbrains.annotations.NotNull
    Used by IntelliJ IDEA IDE for static analysis.
    documentation

  • lombok.NonNull
    Used to control code generation in Project Lombok.
    Placeholder annotation since there is no standard.
    source,
    documentation

  • android.support.annotation.NonNull
    Marker annotation available in Android, provided by support-annotations package
    documentation

  • org.eclipse.jdt.annotation.NonNull
    Used by Eclipse for static code analysis
    documentation

Answers:

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.

Questions:
Answers:

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!

Questions:
Answers:

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.

Questions:
Answers:

Since Oracle decided not to standardize @NonNull (and @Nullable) for the moment, 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:

                                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

Form 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
Questions:
Answers:

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.

Questions:
Answers:

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

Questions:
Answers:

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> 

Questions:
Answers:

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.

Questions:
Answers:

Eclipse has also its own annotations.

org.eclipse.jdt.annotation.NonNull

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

Questions:
Answers:

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😉

Questions:
Answers:

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.

Questions:
Answers:

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)
Questions:
Answers:

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) {}

Questions:
Answers:

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:

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

Questions:
Answers:

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

Questions:
Answers:

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!

Questions:
Answers:

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:

  • Static check: Use @javax.annotations.Nonnull
  • 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(…)
  • Where it fits, use @…NonnullByDefault annotations on class or package level. Create these annotations yourself (examples are easy to find).

For things that may be null (No runtime check required):

  • Use Optional for method return types (only). Either Java8 or Guava.
  • Else, use @javax.annotation.CheckForNull to avoid NPEs

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

Some explanations:

  • jetbrains, eclipse or checkersframework annotations for static checking have no advantage over javax.annotations. jetbrains @NotNull name conflicts with @javax.validation.NotNull.
  • @javax.annotations.Nullable does not mean what you (or your IDE) think it means. Findbugs will ignore it (on members). Sad, but true.
  • For @javax.annotations.CheckForNull, you may have to configure your IDE, or else use it in combination with @javax.annotations.Nullable
  • For static checking, 2 free tools exist: Findbugs and checkersframework.
  • The Eclipse library has @NonNullByDefault, jsr305 only has @ParametersAreNonnullByDefault. Those are mere convenience wrappers applying base annotations to everythin 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)
  • I don’t know about Android, check other answers
Questions:
Answers:

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.

Questions:
Answers:

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.