Je cherche à rendre mon code plus lisible et à utiliser des outils tels que IDE l'inspection de code et/ou l'analyse de code statique (FindBugs et Sonar) afin d'éviter NullPointerExceptions. De nombreux outils semblent incompatibles avec l'annotation _@NotNull
_/_@NonNull
_/_@Nonnull
_ (__) et __ (__) (__) (__) (SOMECODE) __ serait terriblement difficile à lire. Des suggestions de qui est le "meilleur"? Voici la liste des annotations équivalentes que j'ai trouvées:
javax.validation.constraints.NotNull
Créé pour la validation de l'exécution, pas 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 également fonctionner avec Findbugs, 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 d'espace réservé puisqu'il n'y a pas de standard.
source , documentation
Android.support.annotation.NonNull
Annotation de marqueur disponible dans Android, fournie par le package support-annotations
documentation
org.Eclipse.jdt.annotation.NonNull
Utilisé par Eclipse pour l'analyse de code statique
documentation
Puisque JSR 305 (dont le but était de normaliser @NonNull et @Nullable) est en sommeil depuis plusieurs années, 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:
D'un point de vue purement stylistique, j'aimerais éviter toute référence à l'EDI, au framework ou à tout toolkit, à l'exception de Java lui-même.
Ceci exclut:
Ce qui nous laisse soit javax.validation.constraints ou javax.annotation. Le premier vient avec JEE. Si c'est mieux que javax.annotation, qui pourrait éventuellement venir avec JSE ou jamais du tout, est un sujet 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 seule syntaxe qui serait même meilleure: Java.annotation.Nullable. Alors que d'autres paquets passaient javax à Java, javax.annotation serait un pas dans la bonne direction.
J'espérais qu'ils avaient tous fondamentalement la même implémentation triviale, mais une analyse détaillée a montré que ce n'est pas vrai.
D'abord pour les similitudes:
Les annotations @NonNull ont toutes la ligne
public @interface NonNull {}
à l'exception de
Les annotations @Nullable ont toutes la ligne
public @interface Nullable {}
excepté (encore) les org.jetbrains.annotations avec leur implémentation triviale.
Pour les différences:
Un frappant est que
ont tous des annotations d’exécution (@Retention (RUNTIME), tandis que
ne sont que le temps de compilation (@Retention (CLASS)).
Comme décrit dans this SO answer , l'impact des annotations d'exécution est inférieur à ce que l'on pourrait penser, mais ils présentent l'avantage de permettre aux outils de réaliser des contrôles d'exécution en plus de ceux de la compilation. .
Une autre différence importante est où dans le code les annotations peuvent être utilisées. Il y a deux approches différentes. Certains paquets utilisent des contextes de style JLS 9.6.4.1. Le tableau suivant donne un aperçu:
PARAMETRE DE LA METHODE DE CHAMP LOCAL_VARIABLE Android.support.annotation XXX Edu.umd.cs.findbugs.annotations XXXX Org.jetbrains.annotation XXXX Lombok XXXX Javax.validation.constraints XXX
org.Eclipse.jdt.annotation, javax.annotation et org.checkerframework.checker.nullness.qual utilisent les contextes définis dans JLS 4.11, ce qui, à mon avis, est la bonne façon de le faire.
Cela nous laisse avec
dans ce tour.
Pour vous aider à comparer davantage de détails vous-même, je liste ci-dessous le code de chaque annotation. Pour faciliter la comparaison, j'ai supprimé les commentaires, les importations et l'annotation @Documented. (ils avaient tous @Documented sauf 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 de @Nullable:
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 @Nullable, je les énumère donc séparément. Lombok a un @NonNull plutôt ennuyeux. Dans javax.validation.constraints, le @NonNull est en réalité un @NotNull et sa mise en œuvre est 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();
}
}
D'après mon expérience, javax.annotation est au moins pris en charge par Eclipse et par Checker Framework.
Mon annotation idéale serait la syntaxe Java.annotation avec l'implémentation Checker Framework.
Si vous n'avez pas l'intention d'utiliser Checker Framework, le javax.annotation ( JSR-305 ) reste votre meilleur pari. pour le moment.
Si vous êtes prêt à souscrire à Checker Framework, utilisez simplement leur org.checkerframework.checker.nullness.qual.
J'aime beaucoup le Checker Framework , qui est une implémentation de type annotations ( JSR-308 ) qui est utilisé pour implémenter des vérificateurs de défauts comme un vérificateur de nullité. Je n'ai pas vraiment essayé de proposer une comparaison, mais je suis satisfait de cette implémentation.
Je ne suis pas affilié au groupe qui propose le logiciel, mais je suis un fan.
Quatre choses que j’aime dans ce système:
Il a un vérificateur de défauts pour nullness (@Nullable), mais en a aussi un pour immuabilité et interning (et autres). J'utilise le premier (nullness) et j'essaie d'utiliser le second (immutability/IGJ). J'essaie le troisième, mais je ne suis pas sûr de l'utiliser à long terme. Je ne suis pas encore convaincu de l'utilité générale des autres contrôleurs, mais il est agréable de savoir que le cadre lui-même est un système permettant de mettre en œuvre une variété d'annotations et de contrôleurs supplémentaires.
Le paramètre par défaut pour la vérification de la nullité fonctionne bien: non nul sauf les locales (NNEL). En gros, cela signifie que le vérificateur traite par défaut chaque élément (variables d'instance, paramètres de méthode, types génériques, etc.), à l'exception des variables locales, comme si elles avaient un type @NonNull par défaut. Selon la documentation:
La valeur par défaut de NNEL entraîne le plus petit nombre d'annotations explicites dans votre code.
Vous pouvez définir une valeur par défaut différente pour une classe ou pour une méthode si NNEL ne fonctionne pas pour vous.
Ce framework vous permet d’utiliser avec sans créer de dépendance sur le framework en mettant vos annotations dans un commentaire: par exemple /*@Nullable*/
. C'est bien parce que vous pouvez annoter et vérifier une bibliothèque ou un code partagé, tout en pouvant utiliser cette bibliothèque/codée partagée dans un autre projet qui n'utilise pas le framework. C'est une fonctionnalité intéressante. Je me suis habitué à l'utiliser, même si j'ai tendance à activer le framework Checker sur tous mes projets.
La structure a un moyen de annoter les API que vous utilisez et que vous n’avez pas encore annoté pour la nullité en utilisant des fichiers de raccord.
J'utilise celui d'IntelliJ, parce que je m'inquiète surtout du fait qu'IntelliJ signale des éléments susceptibles de générer un NPE. Je conviens qu'il est frustrant de ne pas avoir une annotation standard dans le JDK. On parle de l'ajouter, cela pourrait le rendre dans Java 7. Dans ce cas, il y en aura un de plus à choisir!
Selon la liste des fonctionnalités Java 7 , les annotations de type JSR-308 sont différées sur Java 8. Les annotations JSR-305 ne sont même pas mentionnées.
Il y a quelques informations sur l'état de JSR-305 dans un annexe de la dernière version de JSR-308. Cela inclut l'observation selon laquelle les annotations JSR-305 semblent être abandonnées. La page JSR-305 indique également qu'il est "inactif".
En attendant, la réponse pragmatique consiste à utiliser les types d'annotation pris en charge par les outils les plus largement utilisés ... et à être prêt à les modifier si la situation change.
En fait, JSR-308 ne définit aucun type/classe d'annotation, et il semble qu'ils pensent que cela est hors de portée. (Et ils ont raison, étant donné l'existence de JSR-305).
Cependant, si JSR-308 a vraiment l’intention de passer à Java 8, cela ne me surprendrait pas si l’intérêt pour JSR-305 était ravivé. Autant que je sache, l'équipe JSR-305 n'a pas officiellement abandonné son travail. Ils viennent d'être silencieux depuis plus de 2 ans.
Il est intéressant de noter que Bill Pugh (le responsable technique de JSR-305) est l’un des auteurs de FindBugs.
Pour les projets Android, vous devez utiliser Android.support.annotation.NonNull
et Android.support.annotation.Nullable
. Ces annotations utiles, ainsi que d’autres spécifiques à Android, sont disponibles dans = Bibliothèque de support .
De http://tools.Android.com/tech-docs/support-annotations :
La bibliothèque de support elle-même a également été annotée avec ces annotations. Ainsi, en tant qu'utilisateur de la bibliothèque de support, Android Studio vérifie déjà votre code et signale les problèmes potentiels en fonction de ces annotations.
Si quelqu'un ne cherche que les classes IntelliJ: vous pouvez les obtenir à partir du référentiel maven avec
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>15.0</version>
</dependency>
JSR305 et FindBugs sont créés par la même personne. Les deux sont mal entretenus mais sont aussi standard que possible et sont supportés par tous les principaux IDE. La bonne nouvelle est qu'ils fonctionnent bien tels quels.
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
@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. Ajoutez l'annotation à chaque package: package-info.Java
@NotNullByDefault
package com.example.foo;
UPDATE: Au 12 décembre 2012 JSR 305 est répertorié comme "Dormant". Selon la documentation:
Une JSR qui a été votée comme "dormante" par le Comité exécutif ou qui a atteint la fin de sa vie naturelle.
Il semble que JSR 308 est en cours de création du JDK 8 et bien que le JSR ne définisse pas @NotNull, le Checkers Framework
fait. Au moment de la rédaction de cet article, le plugin Maven est inutilisable à cause de ce bogue: https://github.com/typetools/checker-framework/issues/18
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.
Signalez simplement que l'API de validation Java (javax.validation.constraints.*
) n'est pas accompagnée d'une annotation @Nullable
, ce qui est très utile dans un contexte d'analyse statique. Il est logique de valider un bean d'exécution, car il s'agit de la valeur par défaut pour tout champ non primitif dans Java (c'est-à-dire rien à valider/appliquer). Aux fins indiquées, cela devrait peser par rapport aux alternatives.
Malheureusement, JSR 308
n’ajoutera pas plus de valeurs que la suggestion locale du projet Null ici
Java 8
ne viendra pas avec une seule annotation par défaut ou son propre cadre Checker
. Semblable à Find-Bugs ou à JSR 305
, cette JSR est mal entretenue par un petit groupe d’équipes essentiellement universitaires.
Aucune puissance commerciale derrière elle, donc JSR 308
lance EDR 3
(version préliminaire révisée à JCP
) NOW, alors que Java 8
est censé être livré dans moins de 6 mois: -O Similaire à 310
btw. mais contrairement à 308 Oracle
a pris ses responsabilités à l'écart de ses fondateurs afin de minimiser les dommages que cela causerait à la Java Plateforme.
Chaque projet, fournisseur et classe académique comme ceux derrière le Checker Framework
et JSR 308
créeront leur propre annotation de vérificateur propriétaire.
Rendre le code source incompatible pour les années à venir, jusqu'à ce que quelques compromis populaires puissent être trouvés et éventuellement ajoutés à Java 9
ou 10
, ou via des cadres tels que Apache Commons
ou Google Guava
; - )
Cette réponse est spécifique à Android. Android a un package de support appelé support-annotations
. Cela fournit des dizaines de spécifique à Android annotations et fournit également les plus courantes comme NonNull
, Nullable
etc.
Pour ajouter le package support-annotations , ajoutez la dépendance suivante dans votre build.gradle:
compile 'com.Android.support:support-annotations:23.1.1'
et ensuite utiliser:
import Android.support.annotation.NonNull;
void foobar(@NonNull Foo bar) {}
Faites la distinction entre l'analyse statique et l'analyse d'exécution. Utilisez l'analyse statique pour les éléments internes et l'analyse d'exécution pour les limites publiques de votre code.
Pour les choses qui ne devraient pas être nulles:
Vérification de l'exécution: Utilisez "if (x == null) ..." (dépendance zéro) ou @ javax.validation.NotNull (avec validation du bean) ou @ lombok.NonNull (clair et simple) ou goyave Preconditions.checkNotNull (.. .)
Vérification statique: Utiliser une annotation @NonNull
Cela devrait donner le meilleur résultat: avertissements dans l'EDI, erreurs de Findbugs et checkerframework, exceptions d'exécution significatives.
Ne vous attendez pas à ce que les vérifications statiques soient matures, leur nom n'est pas normalisé et différentes bibliothèques et IDE les traitent différemment, ignorez-les. Les classes javax.annotations. * JSR305 ressemblent à des normes, mais elles ne le sont pas et entraînent la scission de packages avec Java9 +.
Quelques explications sur les notes:
Avant Java9, voici 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’ya aucun moyen de faire en sorte que Spotbugs lève un avertissement lorsqu’un paramètre de méthode nullable est déréférencé (au moment de l’écriture, la version 3.1 de Spotbugs). Peut-être que checkerframework peut le faire.
En attendant que cela soit trié en amont (Java 8?), Vous pouvez également définir vos propres annotations @NotNull
et @Nullable
locales au projet. Cela peut être utile également si 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 {}
Certes, cela servirait en grande partie à des fins décoratives ou d’avenir, étant donné que ce qui précède n’affiche en soi aucun support pour l’analyse statique de ces annotations.
Si vous travaillez sur un gros projet, vous feriez mieux de créer vos propres annotations @Nullable
et/ou @NotNull
.
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 rétention , les annotations ne seront pas disponibles au moment de l'exécution . De ce point de vue, c'est juste une chose interne .
Bien que ce ne soit pas une science stricte, je pense qu'il est plus logique d'utiliser une classe interne pour cela.
@Nullable
/@NotNull
personnalisées.Comment configurer cela dans IntelliJ?
Cliquez sur "l'officier de police" dans le coin inférieur droit de la barre d'état IntelliJ. Et cliquez sur "Configurer les inspections" dans la fenêtre contextuelle. Suivant ...
Si vous développez pour Android, vous êtes un peu lié à Eclipse (édition: au moment de l'écriture, pas plus), qui a ses propres annotations. . Il est inclus dans Eclipse 3.8+ (Juno), mais désactivé par défaut.
Vous pouvez l'activer dans Préférences> Java> Compilateur> Erreurs/Avertissements> Analyse nulle (section réductible en bas).
Cochez "Activer l'analyse des valeurs nulles par annotation"
http://wiki.Eclipse.org/JDT_Core/Null_Analysis#Usage a des recommandations sur les paramètres. Toutefois, si vous avez des projets externes dans votre espace de travail (tel que le SDK de Facebook), ils risquent de ne pas satisfaire à ces recommandations et vous ne voudrez probablement pas les corriger à chaque mise à jour du SDK ;-)
J'utilise:
Il y a une autre façon de faire cela dans Java 8. Je fais 2 choses pour accomplir ce dont j'avais besoin:
Java.util.Optional
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);
}
Ma question est donc la suivante: devons-nous même annoter lorsque vous utilisez Java 8?
Edit: j’ai découvert plus tard que certains considéraient qu’une mauvaise pratique consistait à utiliser Optional
dans les arguments, il y a une bonne discussion avec les avantages et les inconvénients ici Pourquoi devrait-on utiliser Java 8? Facultatif ne pas être utilisé en arguments
Il y a déjà trop de réponses ici, mais (a) nous sommes en 2019 et il n'y a toujours pas de "standard" Nullable
et (b) aucune autre réponse ne fait référence à Kotlin.
La référence à Kotlin est importante, car Kotlin est 100% interopérable avec Java et dispose d'une fonctionnalité de base Null Safety. Lors de l'appel des bibliothèques Java, il peut tirer parti de ces annotations pour permettre aux outils Kotlin de savoir si une API Java peut accepter ou renvoyer null
.
Autant que je sache, les seuls packages Nullable
compatibles avec Kotlin sont org.jetbrains.annotations
et Android.support.annotation
(maintenant androidx.annotation
). Ce dernier est uniquement compatible avec Android et ne peut donc pas être utilisé dans des projets JVM/Java/Kotlin non Android. Cependant, le package JetBrains fonctionne partout.
Donc, si vous développez des packages Java qui devraient également fonctionner dans Android et Kotlin (et être pris en charge par Android Studio et IntelliJ), votre meilleur choix est probablement le JetBrains. paquet.
Maven:
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations-Java5</artifactId>
<version>15.0</version>
</dependency>
Gradle:
implementation 'org.jetbrains:annotations-Java5:15.0'
Si vous construisez votre application à l'aide de Spring Framework, je suggérerais d'utiliser _javax.validation.constraints.NotNull
_ provenant de validation de beans 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 Spring prend en charge les paramètres de méthode et les champs de classe annotés de _javax.validation.constraints.NotNull
_. Pour activer le support, il vous suffit de:
fournissez le fichier api jar pour la validation des beans et le fichier jar avec l'implémentation du validateur des annotations jsr-303/jsr-349 (fourni avec la dépendance Hibernate Validator 5.x):
_<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>
_
fournit MethodValidationPostProcessor au contexte de spring
_ @Configuration
@ValidationConfig
public class ValidationConfig implements MyService {
@Bean
public MethodValidationPostProcessor providePostProcessor() {
return new MethodValidationPostProcessor()
}
}
_
enfin, vous annotez vos classes avec Spring org.springframework.validation.annotation.Validated
et la validation sera automatiquement gérée par Spring.
Exemple:
_@Service
@Validated
public class MyServiceImpl implements MyService {
@Override
public Something doSomething(@NotNull String myParameter) {
// No need to do something like assert myParameter != null
}
}
_
Lorsque vous essayez d'appeler la méthode doSomething et que vous indiquez null comme valeur de paramètre, spring (au moyen de HibernateValidator) renvoie ConstraintViolationException
. Pas besoin de travail manuel ici.
Vous pouvez également valider les valeurs de retour.
Un autre avantage important de _javax.validation.constraints.NotNull
_ pour Beans Validation Framework est qu’il est toujours en cours de développement et que de nouvelles fonctionnalités sont prévues pour la nouvelle version 2.0.
Qu'en est-il de _@Nullable
_? Il n'y a rien de tel dans Beans Validation 1.1. Eh bien, je pourrais soutenir que si vous décidez d'utiliser _@NotNull
_, tout ce qui n'est PAS annoté avec _@NonNull
_ est effectivement "nullable", l'annotation _@Nullable
_ est donc inutile.
Sun n'a-t-il pas le leur maintenant? Qu'est-ce que c'est ça:
http://www.Java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-com.Sun/istack/com.Sun.istack.internal.htm =
Cela semble être fourni avec toutes les versions de Java que j'ai utilisées 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, je vote pour les annotations IntelliJ sur les jetbrains!
Les annotations fournies avec ANTLR 4 constituent une autre option. Suite à demande d'extraction n ° 434 , l'artefact contenant les annotations @NotNull
et @Nullable
inclut un processeur d'annotation qui génère 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 élément ou si @Nullable
est appliqué à un élément de type primitif). Le processeur d'annotation fournit une assurance supplémentaire lors du processus de développement logiciel que les informations véhiculées par l'application de ces annotations sont exactes, y compris en cas d'héritage de méthode.
L'un des avantages de IntelliJ est qu'il n'est pas nécessaire d'utiliser leurs annotations. Vous pouvez écrire le vôtre, ou vous pouvez utiliser ceux de n'importe quel autre outil que vous aimez. Vous n'êtes même pas limité à un seul type. Si vous utilisez deux bibliothèques qui utilisent des annotations @NotNull différentes, vous pouvez indiquer à IntelliJ de les utiliser toutes les deux. Pour ce faire, allez dans "Configurer les inspections", cliquez sur l'inspection "Conditions constantes et exceptions", puis sur le bouton "Configurer les inspections". J'utilise le vérificateur de nullité chaque fois que je le peux. J'ai donc configuré IntelliJ pour utiliser ces annotations, mais vous pouvez le faire fonctionner avec n'importe quel autre outil de votre choix. (Je n'ai pas d'opinion sur les autres outils car j'utilise les inspections d'IntelliJ depuis des années et je les adore.)