1308 Stimmen

Welche @NotNull-Java-Annotation sollte ich verwenden?

Ich möchte meinen Code lesbarer machen und Tools wie IDE-Code-Inspektion und/oder statische Code-Analyse (FindBugs und Sonar) verwenden, um NullPointerExceptions zu vermeiden. Viele der Tools scheinen inkompatibel mit den anderen zu sein. @NotNull / @NonNull / @Nonnull Annotation und die Auflistung aller von ihnen in meinem Code wäre schrecklich zu lesen. Irgendwelche Vorschläge, welche die "beste" ist? Hier ist die Liste der gleichwertigen Annotationen, die ich gefunden habe:

24voto

tkruse Punkte 9304

Unterscheiden Sie zwischen statischer Analyse und Laufzeitanalyse. Verwenden Sie die statische Analyse für interne Dinge und die Laufzeitanalyse für die öffentlichen Grenzen Ihres Codes.

Für Dinge, die nicht null sein sollten:

  • Laufzeitprüfung: Verwendung von "if (x == null) ..." (Null-Abhängigkeit) oder @javax.validation.NotNull (mit Bean-Validierung) oder @lombok.NonNull (schlicht und einfach) oder guavas Preconditions.checkNotNull(...)

    • Verwenden Sie Optional für Methodenrückgabetypen (nur). Entweder Java8 oder Guava.
  • Statische Prüfung: Verwendung einer @NonNull-Anmerkung

  • Wo es passt, verwenden Sie @...NonnullByDefault-Annotationen auf Klassen- oder Paketebene. Erstellen Sie diese Annotationen selbst (Beispiele sind leicht zu finden).

    • Andernfalls @...CheckForNull bei Methodenrückgaben verwenden, um NPEs zu vermeiden

Dies sollte das beste Ergebnis liefern: Warnungen in der IDE, Fehler durch Findbugs und checkerframework, sinnvolle Laufzeitausnahmen.

Erwarten Sie nicht, dass statische Prüfungen ausgereift sind, ihre Benennung ist nicht

S

  • F
  • S h )
  • j
  • j
  • @ h )
  • F
  • T
  • U
  • U
  • U
  • A

B

// 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);
    }
}

N

S

F

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

T

20voto

Bruno Eberhard Punkte 1556

Falls jemand nur nach den IntelliJ-Klassen sucht: Sie können sie aus dem Maven-Repository beziehen mit

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

19voto

Gili Punkte 80842

JSR305 und FindBugs werden von der gleichen Person verfasst. Beide werden schlecht gepflegt, gehören aber zum Standard und werden von allen großen IDEs unterstützt. Die gute Nachricht ist, dass sie so, wie sie sind, gut funktionieren.

Hier erfahren Sie, wie Sie @Nonnull standardmäßig auf alle Klassen, Methoden und Felder anwenden. Siehe https://stackoverflow.com/a/13319541/14731 y https://stackoverflow.com/a/9256595/14731

  1. Definieren Sie @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. Fügen Sie die Anmerkung zu jedem Paket hinzu: package-info.java

@NotNullByDefault
package com.example.foo;

UPDATE : Stand: 12. Dezember 2012 JSR 305 ist als "ruhend" aufgeführt. Laut der Dokumentation:

Ein JSR, der vom Exekutivausschuss als "ruhend" eingestuft wurde, oder ein JSR, der das Ende seiner natürlichen Lebensspanne erreicht hat.

Es sieht so aus JSR 308 es in das JDK 8 aufgenommen, und obwohl der JSR @NotNull nicht definiert, ist die zugehörige Checkers Framework tut. Zum Zeitpunkt der Erstellung dieses Artikels ist das Maven-Plugin aufgrund dieses Fehlers unbrauchbar: https://github.com/typetools/checker-framework/issues/183

12voto

Horcrux7 Punkte 22751

Eclipse hat auch seine eigenen Anmerkungen.

org.eclipse.jdt.annotation.NonNull

Siehe unter http://wiki.eclipse.org/JDT_Core/Null_Analysis für Details.

11voto

Ophir Radnitz Punkte 1623

Ich weise nur darauf hin, dass die Java Validation API ( javax.validation.constraints.* ) kommt nicht mit einer @Nullable Annotation, die in einem statischen Analysekontext sehr wertvoll ist. Sie ist sinnvoll für die Validierung von Beans zur Laufzeit, da dies der Standard für alle nicht-primitiven Felder in Java ist (d.h. nichts zu validieren/erzwingen). Für die genannten Zwecke sollte dies gegenüber den Alternativen abwägen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X