Quelle annotation Java @NotNull dois-je utiliser?

je cherche à rendre mon code plus lisible ainsi qu'à utiliser des outils comme L'inspection de code IDE et/ou l'analyse de code statique (FindBugs et Sonar) pour éviter les exceptions nulles. Beaucoup d'outils semblent incompatibles les uns avec les autres' @NotNull / @NonNull / @Nonnull l'annotation et l'énumération de tous dans mon code seraient terribles à lire. Toutes les suggestions de laquelle est la "meilleure"? Voici la liste des annotations équivalentes que j'ai trouvées:

  • javax.validation.constraints.NotNull

    créé pour la validation d'exécution, pas pour l'analyse statique.

    documentation

  • edu.umd.cs.findbugs.annotations.NonNull

    utilisé par Findbugs analyse statique et donc Sonar (maintenant Sonarqube )

    documentation

  • javax.annotation.Nonnull

    cela pourrait fonctionner avec Findbugs aussi, mais JSR-305 est inactif. (Voir aussi: Quel est le statut de JSR 305? ) source

  • org.jetbrains.annotations.NotNull

    utilisé par IntelliJ IDEA IDE pour l'analyse statique.

    documentation

  • lombok.NonNull

    utilisé pour contrôler la génération de code dans Project Lombok .

    Annotation du paramètre Placeholder puisqu'il n'y a pas de norme.

    source , documentation

  • android.support.annotation.NonNull

    annotation de marqueur disponible sur Android, fournie par le paquet support-annotations

    documentation

  • org.eclipse.jdt.annotation.NonNull

    utilisé par Eclipse pour l'analyse de code statique

    documentation

768
demandé sur David Tonhofer 2011-02-11 01:05:35

20 réponses

j'aime beaucoup le Checker "Cadre de 151930920" , qui est une implémentation de type annotations ( JSR-308 ) qui est utilisé pour mettre en œuvre défaut pions comme un nullness checker. Je n'ai pas vraiment essayé d'autres pour offrir une comparaison, mais j'ai été heureux avec cette implémentation.

Je ne suis pas affilié au groupe qui offre le logiciel, mais je suis un fan.

quatre choses que j'aime à ce sujet système:

  1. il a un vérificateur de défauts pour nullness (@Nullable), mais il a aussi ceux pour immutabilité et interning (et autres). J'utilise le premier (nullness) et j'essaie d'utiliser le second (immutabilité/IGJ). J'essaie la troisième, mais je ne suis pas sûr de l'utiliser à long terme. Je ne suis pas convaincu de l'utilité générale de l'autre checkers encore, mais il est agréable de savoir que le cadre lui-même est un système pour mettre en œuvre une variété d'annotations supplémentaires et de checkers.

  2. le paramètre par défaut pour la vérification de la nullité fonctionne bien: Non-null excepté les locaux (NNEL). Fondamentalement, cela signifie que par défaut le vérificateur traite tout (variables d'instance, paramètres de méthode, types génériques, etc.) sauf les variables locales comme si elles avaient un type @NonNull par défaut. Selon la documentation:

    le défaut NNEL conduit au plus petit nombre d'annotations explicites dans votre code.

    vous pouvez définir un défaut différent pour une classe ou pour une méthode si NNEL ne fonctionne pas pour vous.

  3. ce framework vous permet d'utiliser avec sans créer de dépendance sur le framework en incluant vos annotations dans un commentaire: par exemple /*@Nullable*/ . C'est agréable parce que vous pouvez annoter et vérifier une bibliothèque ou un code partagé, mais encore être en mesure d'utiliser cette bibliothèque/codé partagé dans un autre projet qui n'utilise pas le cadre. C'est une fonctionnalité intéressante. J'ai pris l'habitude de l'utiliser, même si j'ai tendance à activer le Vérificateur de Cadre sur tous mes projets.

  4. Le cadre a un moyen de annoter APIs que vous utilisez qui ne sont pas déjà annotés pour la nullité en utilisant des fichiers stub.

78
répondu Bert F 2017-01-21 06:17:28

depuis Oracle a décidé de ne pas standardiser @NonNull (et @Nullable) pour le moment, je crains qu'il n'y ait pas de bonne réponse. Tout ce que nous pouvons faire est de trouver une solution pragmatique et la mienne est la suivante:

syntaxe

d'un point de vue purement stylistique, je voudrais éviter toute référence à IDE, framework ou toolkit, à l'exception de Java lui-même.

Ce règlement:

  • android.soutien.annotation
  • edu.umd.cs.findbugs.annotations
  • org.Eclipse.jdt.annotation
  • org.jetbrains.annotations
  • org.checkerframework.vérificateur.nullness.qual
  • lombok.NonNull

ce qui nous laisse avec soit javax.validation.contraintes ou javax.annotation. Le premier vient avec JEE. Si c'est mieux que javax.l'annotation, qui pourrait éventuellement venir avec JSE ou jamais du tout, est une question de débat. Personnellement, je préfère javax.annotation parce que je n'aimerais pas la dépendance JEE.

cela nous laisse avec

javax.annotation

qui est aussi le plus court.

il n'y a qu'une syntaxe qui serait encore meilleure: java.annotation.Nullable. Comme autres colis diplôme de javax de java dans le passé, le javax.annotation serait être un pas dans la bonne direction.

mise en œuvre

j'espérais qu'ils aient tous la même mise en œuvre triviale, mais une analyse détaillée a montré que ce n'est pas vrai.

premier pour les similitudes:

les annotations @NonNull ont toutes la ligne

public @interface NonNull {}

sauf pour

  • org.jetbrains.annotations qui l'appelle @NotNull et a une mise en œuvre triviale
  • javax.annotation dont la mise en œuvre est plus longue
  • javax.validation.contraintes qui l'appelle aussi @NotNull et a une mise en œuvre

les annotations @ nulles ont toutes la ligne

public @interface Nullable {}

sauf pour (encore une fois) de l'org.jetbrains.annotation avec leur implémentation triviale.

pour les différences:

un frappant est que

  • javax.annotation
  • javax.validation.contraintes
  • org.checkerframework.vérificateur.nullness.qual

tous ont des annotations d'exécution (@Retention (RUNTIME), tandis que

  • android.soutien.annotation
  • edu.umd.cs.findbugs.annotations
  • org.Eclipse.jdt.annotation
  • org.jetbrains.annotations

ne sont que de la compilation (@Retention(CLASSE)).

Comme décrit dans cette SORTE de réponse l'impact de l'exécution des annotations est plus petit qu'on pourrait le penser, mais ils ont l'avantage d'outils permettant d'effectuer des contrôles d'exécution en plus de le moment de la compilation.

une autre différence importante est dans le code les annotations peuvent être utilisées. Il existe deux approches différentes. Certains paquets utilisent des contextes de style JLS 9.6.4.1. Le tableau suivant donne un aperçu:


                                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 et org.checkerframework.vérificateur.nullness.utiliser les contextes définis dans JLS 4.11, qui est à mon avis la bonne façon de faire.

cela nous laisse avec

  • javax.annotation
  • org.checkerframework.vérificateur.nullness.qual

dans ce round.

Code

pour vous aider à comparer d'autres détails vous-même, j'énumère le code de chaque annotation ci-dessous. Pour rendre la comparaison plus facile j'ai enlevé commentaires, importations et l'annotation "documentée". (ils avaient tous @documenté sauf pour les classes du paquet Android). J'ai réorganisé les lignes et les champs @Target et normalisé les 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 {}

pour être complet, voici les implémentations @ nullables:

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

les deux paquets suivants n'ont pas de @Nullable, donc je les Liste séparément lombok a un @NonNull assez ennuyeux. Dans javax.validation.contraintes le @NonNull est en fait un @NotNull et il a une mise en œuvre plus longue.

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

D'après mon expérience javax.l'annotation est au moins supportée par Eclipse et le cadre de vérification de la boîte.

résumé

mon annotation idéale serait le java.la syntaxe d'annotation avec l'implémentation du Framework Checker.

si vous n'avez pas l'intention d'utiliser le Checker javax .annotation ( JSR-305 ) est toujours votre meilleur pari pour le moment.

si vous êtes prêt à acheter dans le cadre de vérificateur juste utiliser leur org.checkerframework.vérificateur.nullness.qual.


Sources

  • android.soutien.l'annotation de android 5.1.1_r1.jar
  • edu.umd.cs.findbugs.annotations de findbugs-annotations-1.0.0.jar
  • org.Eclipse.jdt.l'annotation de org.Eclipse.jdt.annotation_2.1.0.v20160418-1457.jar
  • org.jetbrains.les annotations de jetbrains-annotations-13.0.jar
  • javax.l'annotation de gwt-dev-2.5.1-sources.jar
  • org.checkerframework.vérificateur.nullness.qual de checker-cadre-2.1.9.zip
  • lombok from lombok commit f6da35e4c4f3305 ❚ 1b415e2ab1b9ef8a9120b4
  • javax.validation.contraintes validation-api-1.0.0.GA-sources.jar
73
répondu Ludwig Weinzierl 2018-06-30 00:30:12

j'utilise celui D'IntelliJ, parce que je suis surtout préoccupé par IntelliJ signaler des choses qui pourraient produire un NPE. Je suis d'accord que c'est frustrant de ne pas avoir une annotation standard dans le JDK. On parle de l'ajouter, ça pourrait faire Java 7. Auquel cas il y aura un plus grand choix!

51
répondu Sam Barnum 2011-02-10 22:09:00

, Selon le Java 7 liste des fonctionnalités de JSR-308 annotations de type sont reportés à Java 8. Les annotations JSR-305 ne sont même pas mentionnées.

Il est un peu d'info sur l'état de la JSR-305 dans un annexe de la dernière JSR-308 projet. Cela inclut l'observation que les annotations JSR-305 semblent être abandonnées. La page JSR-305 l'affiche également comme "inactive".

entre-temps, le la réponse pragmatique est d'utiliser les types d'annotation qui sont soutenus par les outils les plus largement utilisés ... et soyez prêt à les changer si la situation change.


en fait, JSR-308 ne définit aucun type/classe d'annotation, et il semble qu'ils pensent qu'il est hors de portée. (Et ils ont raison, compte tenu de L'existence du JSR-305).

cependant, si JSR-308 ressemble vraiment à faire dans Java 8, il ne me surprendrait pas si reprise de L'intérêt pour le JSR-305. AFAIK, L'équipe JSR-305 n'a pas officiellement abandonné son travail. Ils sont calmes depuis plus de 2 ans.

il est intéressant que Bill Pugh (le chef de file technologique pour JSR-305) est l'un des gars derrière FindBugs.

32
répondu Stephen C 2017-01-21 20:53:35

pour les projets Android, vous devez utiliser android.support.annotation.NonNull et android.support.annotation.Nullable . Ces annotations et d'autres utiles spécifiques à Android sont disponibles dans la Support Library .

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

la bibliothèque de soutien elle-même a également été annotée avec ces annotations, de sorte qu'en tant qu'utilisateur de la bibliothèque de soutien, Android Studio va Vérifiez déjà votre code et signalez les problèmes potentiels sur la base de ces annotation.

25
répondu James Wald 2015-04-22 22:01:41

JSR305 et FindBugs sont écrits par la même personne. Les deux sont mal entretenus, mais sont aussi standards qu'ils le deviennent et sont soutenus par toutes les grandes IDEs. La bonne nouvelle, c'est qu'ils fonctionnent bien.

Voici comment appliquer @Nonnull à toutes les classes, méthodes et champs par défaut. Voir https://stackoverflow.com/a/13319541/14731 et https://stackoverflow.com/a/9256595/14731

  1. Définir @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. Ajouter l'annotation suivante à chaque colis: package-info.java

@NotNullByDefault
package com.example.foo;

UPDATE : en date du 12 décembre 2012 JSR 305 est répertorié comme"inactif". Selon la documentation:

UN JSR qui a été voté comme "endormi" par le Comité Exécutif, ou celui qui a atteint la fin de sa durée de vie.

il ressemble à JSR 308 1519200920" est ce qui en fait JDK 8 et bien que le JSR ne définit pas @NotNull, l'accompagnement Checkers Framework fait. Au moment de la rédaction, le plugin Maven est inutilisable à cause de ce bug: https://github.com/typetools/checker-framework/issues/183

17
répondu Gili 2017-05-23 11:55:02

si n'importe qui est juste à la recherche des classes IntelliJ: vous pouvez les obtenir à partir du dépôt maven avec

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations</artifactId>
    <version>15.0</version>
</dependency> 
17
répondu Bruno Eberhard 2017-05-17 19:52:22

Eclipse a aussi ses propres annotations.

org.eclipse.jdt.annotation.NonNull

voir http://wiki.eclipse.org/JDT_Core/Null_Analysis pour plus de détails.

12
répondu Horcrux7 2016-06-02 10:25:21

vient de souligner que L'API de Validation Java ( javax.validation.constraints.* ) ne vient pas avec une annotation @Nullable , ce qui est très utile dans un contexte d'analyse statique. Cela a du sens pour la validation des fèves d'exécution car c'est la valeur par défaut pour tout champ non primitif en Java (c'est-à-dire rien à valider/renforcer). Aux fins énoncées, cela devrait peser en faveur des solutions de rechange.

11
répondu Ophir Radnitz 2011-08-01 12:07:31

malheureusement, JSR 308 n'ajoutera pas plus de valeurs que ce projet local pas nulle suggestion ici

Java 8 ne sera pas fourni avec une seule annotation par défaut ou son propre cadre Checker . Similaire à Find-bugs ou JSR 305 , ce JSR est mal entretenu par un petit groupe d'équipes essentiellement académiques.

No commercial de la puissance derrière elle, donc JSR 308 lance EDR 3 (Début du Projet de Révision à JCP ) Maintenant, alors que Java 8 est censé être expédié en moins de 6 mois: - O Similaire à 310 btw. mais contrairement à 308 Oracle a pris la charge de cela maintenant loin de ses fondateurs pour minimiser le mal qu'il fera à la plate-forme Java.

chaque projet, vendeur et classe académique comme ceux derrière le Checker Framework et JSR 308 va créer sa propre annotation de vérificateur propriétaire.

rendre le code source incompatible pour les années à venir, jusqu'à quelques des compromis populaires pourraient être trouvés et peut-être ajoutés à Java 9 ou 10 , ou via des cadres comme Apache Commons ou Google Guava ; -)

7
répondu Werner Keil 2013-04-01 10:33:43

Android

cette réponse est spécifique à Android. Android a le paquet de soutien appelé support-annotations . Cela fournit douzaines de spécifique Android annotations et fournit également communs comme NonNull , Nullable etc.

pour ajouter support-annotations paquet, ajouter la dépendance suivante dans votre build.Grad le:

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

et ensuite utiliser:

import android.support.annotation.NonNull;

void foobar(@NonNull Foo bar) {}
7
répondu Shubham Chaudhary 2016-01-27 11:16:52

en attendant que cela soit réglé en amont (Java 8?), vous pouvez également définir votre propre projet-annotations locales @NotNull et @Nullable . Cela peut être utile aussi dans le cas où vous travaillez avec Java SE, où javax.validation.constraints n'est pas disponible par défaut.

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

il est vrai que cela serait en grande partie à des fins décoratives ou de protection de l'avenir, étant donné que ce qui précède n'ajoute évidemment pas en soi un soutien quelconque à la l'analyse statique de ces annotations.

4
répondu Arto Bendiken 2017-05-23 11:55:02

si vous développez pour android, vous êtes un peu lié à Eclipse (edit: au moment de l'écriture, plus maintenant), qui a ses propres annotations. Il est inclus dans Eclipse 3.8+ (Juno), mais désactivé par défaut.

vous pouvez l'activer à Preferences > Java > Compiler > Errors/Warnings > Null analysis (section repliable en bas).

cochez la Case "Activer l'annotation basée sur null" l'analyse

http://wiki.eclipse.org/JDT_Core/Null_Analysis#Usage a des recommandations sur les réglages. Cependant, si vous avez des projets externes dans votre espace de travail (comme le SDK facebook), ils peuvent ne pas satisfaire ces recommandations, et vous ne voulez probablement pas les corriger avec chaque mise à jour du SDK; -)

j'utilise:

  1. pointeur Null accès: message d'Erreur
  2. Violation de la spécification nulle: erreur (liée au point #1))
  3. Potentiel de pointeur null accès: Avertissement (sinon facebook SDK aurait mises en garde)
  4. conflit entre annotations nulles et inférence nulle: avertissement (lié au point #3)
4
répondu chaqke 2014-12-02 19:52:29

faire la distinction entre l'analyse statique et l'analyse d'exécution. Utilisez l'analyse statique pour les choses internes, et l'analyse d'exécution pour les limites publiques de votre code.

pour des choses qui ne devraient pas être nulles:

  • moment de l'Exécution: Utilisation de "if (x == null) ..."(dépendance zéro) ou @javax.validation.NotNull (avec bean validation) ou @lombok.Conditions préalables NonNull (simple et simple) ou guavas.checkNotNull(...)

    • facultatif pour les types de méthode de déclaration (seulement). Soit Java8, soit Goyave.
  • Contrôle statique: utilisez une annotation @NonNull

  • Où il s'inscrit, utilisez @...Annotations NonnullByDefault au niveau de la classe ou du paquet. Créer ces annotations vous-même (les exemples sont faciles à trouver).
    • Sinon, utilisez @...Check fornull on méthode retourne pour éviter les NPE

cela devrait donner le meilleur résultat: des avertissements dans L'IDE, des erreurs par Findbugs et checkerfram framework, des exceptions significatives à l'exécution.

ne s'attendent pas à ce que les vérifications statiques soient Matures, leur appellation n'est pas normalisée et différentes bibliothèques et IDEs les traitent différemment, les ignorent. Le javax JSR305.annotation.* les classes ressemblent à standard, mais elles ne le sont pas, et elles provoquent des paquets fractionnés avec Java9+.

Quelques notes d'explications:

  • Findbugs/spotbugs/jsr305 annotations with package javax.validation.* conflit avec D'autres modules dans Java9+, peut-être aussi violer la licence Oracle
  • Spotbugs annotations dépend toujours de jsr305/findbugs annotations au compile-time (au moment de la rédaction de https://github.com/spotbugs/spotbugs/issues/421 )
  • jetbrains @NotNull nom en conflit avec @ javax.validation.NotNull.
  • jetbrains, eclipse ou checkersfram Framework annotations for static checking ont l'avantage sur javax.annotations qu'ils ne s'opposent pas à D'autres modules dans Java9 et supérieur
  • @javax.annotation.Nullable ne veut pas dire trouver ce que vous (ou votre IDE) pensez qu'il signifie. Findbugs l'ignorera (sur les membres). Triste, mais vrai.
  • pour le contrôle statique en dehors d'un IDE, 2 outils gratuits existent: Spotbugs (anciennement Findbugs) et checkersfram Framework.
  • la bibliothèque Eclipse a @NonNullByDefault, jsr305 a seulement @ParametersAreNonnullByDefault. Ce sont de simples emballages de commodité appliquant des annotations de base à tout dans un paquet (ou une classe), vous pouvez facilement créer votre propre. Ceci peut être utilisé sur l'emballage. Cela peut entrer en conflit avec le code généré (par exemple lombok).
  • Les annotations
  • Eclipse jdt ne sont pas applicables aux retours de méthode statiques et autres affaires 1519110920"
  • utiliser lombok comme une dépendance exportée devrait être évité pour les bibliothèques que vous partagez avec d'autres personnes, les dépendances moins transitives, le meilleur
  • en utilisant le cadre de validation des haricots est puissant, mais nécessite un haut niveau de frais généraux, de sorte que c'est trop pour éviter la vérification manuelle nulle.
  • utiliser optionnel pour les champs et les paramètres de méthode est controversé (vous pouvez trouver des articles à ce sujet facilement)
  • Android null annotations font partie de la bibliothèque de soutien Android, ils viennent avec beaucoup d'autres classes, et ne jouent pas bien avec d'autres annotations / outils

avant Java9, c'est ma recommandation:

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


// file: PublicApi
package example;

public class PublicApi {

    /**
     * @param firstname MUST NOT be null
     * @param lastname MUST NOT be null
     */
    public Person createPerson(
            // Spotbugs ignores the param annotations, but IDEs will show problems
            @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);
    }
}

notez qu'il n'y a aucun moyen de faire lever un avertissement Spotbugs lorsqu'un paramètre de méthode nullable est déréférencé (au moment de l'écriture, versio 3.1 de SPotbugs). Checkerframork peut peut-être faire ça.

4
répondu tkruse 2018-08-11 09:58:49

il y a une autre façon de le faire en Java 8. Je fais deux choses pour accomplir ce dont j'avais besoin:

  1. Faire nullable champs explicite avec des types en les enveloppant nullable les champs avec java.util.Optional
  2. vérification que tous les champs non nulles ne sont pas nuls au moment de la construction avec java.util.Objects.requireNonNull

exemple:

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

Donc ma question est, avons-nous encore besoin d'annoter quand en utilisant java 8?

modifier: j'ai découvert plus tard que certains considèrent une mauvaise pratique d'utiliser Optional dans les arguments, Il ya une bonne discussion avec pour et contre ici Pourquoi est-ce que L'option de Java 8 ne devrait pas être utilisé dans les arguments

3
répondu Mozart Brocchini 2017-05-23 12:10:45

le soleil n'a-t-il pas le sien? Qu'est-ce que c'est?:

http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-com.sun/istack/com.sun.istack.internal.htm

cela semble être emballé avec toutes les versions de Java que j'ai utilisé au cours des dernières années.

Edit: , Comme mentionné dans les commentaires ci-dessous, vous ne voulez probablement pas à les utiliser. Dans ce cas, mon vote est pour les annotations IntelliJ jetbrains!

2
répondu Nate W. 2011-02-10 23:06:25

si vous construisez votre application en utilisant Spring Framework je suggérerais d'utiliser javax.validation.constraints.NotNull comming de validation haricots empaqueté dans la dépendance suivante:

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

le principal avantage de cette annotation est que le ressort supporte à la fois les paramètres de la méthode et les champs de classe annotés avec javax.validation.constraints.NotNull . Tout ce que vous devez faire pour activer le support est:

  1. fourniture le JAR de l'api pour la validation des haricots et le jar avec mise en œuvre du validateur des annotations jsr-303/jsr-349 (qui est livré avec le validateur D'hibernation 5.x dépendance):

    <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. fournir MethodValidationPostProcessor de printemps du contexte

      @Configuration
      @ValidationConfig
      public class ValidationConfig implements MyService {
    
            @Bean
            public MethodValidationPostProcessor providePostProcessor() {
                  return new MethodValidationPostProcessor()
            }
      }
    
  3. enfin vous annotez vos classes avec org.springframework.validation.annotation.Validated de Spring et la validation sera traitée automatiquement par Printemps.

exemple:

@Service
@Validated
public class MyServiceImpl implements MyService {

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

quand vous essayez d'appeler la méthode doSomething et passer null comme valeur du paramètre, le ressort (au moyen de HibernateValidator) lancera ConstraintViolationException . Pas besoin de manuall travail ici.

vous pouvez également valider les valeurs de retour.

un autre avantage important de javax.validation.constraints.NotNull comming for Beans Validation Framework est qu'à l'heure actuelle, il est encore développées et de nouvelles fonctionnalités sont prévues pour la nouvelle version 2.0.

et @Nullable ? Il n'y a rien de Tel dans la Validation des haricots 1.1. Eh bien, je pourrais argumenter que si vous décidez d'utiliser @NotNull que tout ce qui N'est pas annoté avec @NonNull est effectivement "nullable", de sorte que l'annotation @Nullable est inutile.

2
répondu walkeros 2017-05-31 11:58:21

si vous travaillez sur un grand projet, vous pouvez être mieux de créer votre propre" 151970920 @Nullable et/ou @NotNull annotations.

par exemple:

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

si vous utilisez la bonne Politique de conservation , alors les annotations ne seront pas disponibles à l'exécution . De ce point de vue, c'est juste une chose interne .

même si ce n'est pas une science stricte, je pense qu'il est plus logique d'utiliser une classe interne pour elle.

  • C'est une chose. (aucun impact fonctionnel ou technique)
  • avec beaucoup beaucoup beaucoup d'usages.
  • IDE est comme IntelliJ support custom @Nullable / @NotNull annotations.
  • la Plupart des cadres préfèrent utiliser leur propre version.

questions supplémentaires (voir commentaires):

comment configurer ceci dans IntelliJ ?

cliquez sur "policier" dans le coin inférieur droit de la barre de statut IntelliJ. Et cliquez sur "Configurer les inspections" dans le popup. Prochain. .. configure annotations

2
répondu bvdb 2017-10-27 10:52:19

une autre option est les annotations fournies avec ANTLR 4. Après demande D'extraction n ° 434 , l'artefact contenant les annotations @NotNull et @Nullable comprend un processeur d'annotation qui produit des erreurs de compilation et/ou des avertissements dans le cas où l'un de ces attributs est mal utilisé (par exemple, si les deux sont appliqués au même article, ou si @Nullable est appliqué à un article avec un type primitif). Le processeur d'annotation fournit une assurance supplémentaire au cours du processus de développement du logiciel que l'information transmise par l'application de ces annotations est exacte, y compris dans les cas d'héritage de méthode.

1
répondu Sam Harwell 2014-01-21 21:35:57

une des bonnes choses à propos D'IntelliJ est que vous n'avez pas besoin d'utiliser leurs annotations. Vous pouvez écrire votre propre, ou vous pouvez utiliser ceux de tout autre outil que vous aimez. Tu n'es même pas limité à un seul type. Si vous utilisez deux bibliothèques qui utilisent des annotations @NotNull différentes, vous pouvez dire à IntelliJ de les utiliser toutes les deux. Pour ce faire, allez dans "Configurer les Inspections", cliquez sur l'inspection "conditions constantes et Exceptions" et appuyez sur le bouton "Configurer les inspections". J'utilise le Nullness Checker partout où je peux, donc J'ai mis en place IntelliJ pour utiliser ces annotations, mais vous pouvez le faire fonctionner avec tout autre outil que vous voulez. (Je n'ai pas d'opinion sur les autres outils parce que J'utilise les inspections D'IntelliJ depuis des années, et je les adore.)

0
répondu MiguelMunoz 2018-07-16 20:43:49