Je peux voir que @Nullable
et les @Nonnull
annotations pourraient être utiles pour empêcher les NullPointerException
s, mais elles ne se propagent pas très loin.
- L'efficacité de ces annotations diminue complètement après un niveau d'indirection, donc si vous n'en ajoutez que quelques-unes, elles ne se propagent pas très loin.
- Étant donné que ces annotations ne sont pas bien appliquées, il y a un risque de supposer qu'une valeur marquée par
@Nonnull
n'est pas nulle et par conséquent de ne pas effectuer de vérifications nulles.
Le code ci - dessous provoque un paramètre marqué par @Nonnull
être null
sans soulever de plaintes. Il jette un NullPointerException
quand il est exécuté.
public class Clazz {
public static void main(String[] args){
Clazz clazz = new Clazz();
// this line raises a complaint with the IDE (IntelliJ 11)
clazz.directPathToA(null);
// this line does not
clazz.indirectPathToA(null);
}
public void indirectPathToA(Integer y){
directPathToA(y);
}
public void directPathToA(@Nonnull Integer x){
x.toString(); // do stuff to x
}
}
Existe-t-il un moyen de rendre ces annotations plus strictement appliquées et / ou de se propager davantage?
java
annotations
nullpointerexception
nullable
code-standards
Mike Rylander
la source
la source
@Nullable
ou@Nonnull
, mais s'ils en valent la peine, il est très "susceptible de@Nonnull
lors de l'appel d'une@Nonnull
méthode avec une variable Nullable. Bien sûr, la conversion avec une annotation n'est pas possible dans Java 7, mais Java 8 ajoutera la possibilité d'appliquer des annotations à l'utilisation d'une variable, y compris les casts. Cela peut donc devenir possible à implémenter en Java 8.(@NonNull Integer) y
est syntaxiquement possible, mais un compilateur n'est pas autorisé à émettre un code d'octet spécifique basé sur l'annotation. Pour les assertions d'exécution, de minuscules méthodes d'assistance sont suffisantes, comme indiqué dans bugs.eclipse.org/442103 (par exempledirectPathToA(assertNonNull(y))
) - mais attention, cela ne fait qu'échouer rapidement. Le seul moyen sûr est d'effectuer une vérification réelle de null (plus, espérons-le, une implémentation alternative dans la branche else).@Nonnull
et dont@Nullable
vous parlez, car il y a plusieurs annoations similaires (voir cette question ). Parlez-vous des annotations dans le packagejavax.annotation
?Réponses:
Réponse courte: je suppose que ces annotations ne sont utiles que pour que votre IDE vous avertisse des erreurs de pointeur potentiellement nulles.
Comme dit dans le livre "Clean Code", vous devriez vérifier les paramètres de votre méthode publique et aussi éviter de vérifier les invariants.
Un autre bon conseil est de ne jamais renvoyer de valeurs nulles, mais d'utiliser à la place un motif d'objet nul .
la source
Optional
type au lieu de plainnull
Optional
et nullable dans ce cas est que cela indiqueOptional
mieux que cette valeur peut être intentionnellement vide. Certes, ce n'est pas une baguette magique et pendant l'exécution, elle peut échouer exactement de la même manière qu'une variable Nullable. Cependant, la réception de l'API par le programmeur est meilleureOptional
à mon avis.Outre que votre IDE vous donne des conseils lorsque vous passez
null
à des méthodes qui s'attendent à ce que l'argument ne soit pas nul, il y a d'autres avantages:Cela peut aider votre code à être plus maintenable (puisque vous n'avez pas besoin de
null
vérifications) et moins sujet aux erreurs.la source
assert
. Je trouve@Nullable
et@Nonnull
être des idées utiles, mais j'aimerais plus de force derrière elles, plutôt que de faire des hypothèses sur ce que l'on pourrait en faire, ce qui laisse encore ouverte la possibilité de ne rien faire avec elles.Je pense que cette question originale pointe indirectement vers une recommandation générale selon laquelle la vérification du pointeur nul au moment de l'exécution est toujours nécessaire, même si @NonNull est utilisé. Reportez-vous au lien suivant:
Nouvelles annotations de type de Java 8
Dans le blog ci-dessus, il est recommandé que:
la source
En compilant l'exemple d'origine dans Eclipse à la conformité 1.8 et avec l'analyse nulle basée sur les annotations activée, nous obtenons cet avertissement:
Cet avertissement est formulé par analogie avec les avertissements que vous recevez lorsque vous mélangez du code généré avec du code hérité en utilisant des types bruts ("conversion non cochée"). Nous avons exactement la même situation ici: la méthode
indirectPathToA()
a une signature «héritée» en ce qu'elle ne spécifie aucun contrat nul. Les outils peuvent facilement signaler cela, ils vous poursuivront donc dans toutes les allées où des annotations nulles doivent être propagées mais ne le sont pas encore.Et lorsque vous utilisez un intelligent,
@NonNullByDefault
nous n'avons même pas à le dire à chaque fois.En d'autres termes: le fait que les annotations nulles "se propagent très loin" peut dépendre de l'outil que vous utilisez et de la rigueur avec laquelle vous vous occupez de tous les avertissements émis par l'outil. Avec les annotations nulles TYPE_USE, vous avez enfin la possibilité de laisser l'outil vous avertir de tous les NPE possibles dans votre programme, car la nullité est devenue une propriété intrinsèque du système de types.
la source
Je conviens que les annotations "ne se propagent pas très loin". Cependant, je vois l'erreur du côté du programmeur.
Je comprends l'
Nonnull
annotation comme une documentation. La méthode suivante exprime qu'elle requiert (comme condition préalable) un argument non nulx
.L'extrait de code suivant contient alors un bogue. La méthode appelle
directPathToA()
sans appliquer ce quiy
est non nul (c'est-à-dire qu'elle ne garantit pas la condition préalable de la méthode appelée). Une possibilité est d'ajouter également uneNonnull
annotation àindirectPathToA()
(propager la précondition). La deuxième possibilité consiste à vérifier la nullité dey
inindirectPathToA()
et à éviter l'appel àdirectPathToA()
wheny
is null.la source
@Nonnull
to haveindirectPathToA(@Nonnull Integer y)
est à mon humble avis une mauvaise pratique: vous devrez maintenir la propagation sur la pile d'appels complète (donc si vous ajoutez unnull
enregistrementdirectPathToA()
, vous devrez remplacer@Nonnull
par@Nullable
dans la pile d'appels complète). Ce serait un énorme effort de maintenance pour les grandes applications.Ce que je fais dans mes projets est d'activer l'option suivante dans l'inspection de code "Conditions constantes et exceptions":
Suggérer une annotation @Nullable pour les méthodes qui peuvent éventuellement renvoyer null et signaler des valeurs nullables passées à des paramètres non annotés
Lorsqu'il est activé, tous les paramètres non annotés seront traités comme non nuls et vous verrez donc également un avertissement sur votre appel indirect:
Pour des vérifications encore plus solides, le Checker Framework peut être un bon choix (voir ce joli tutoriel .
Remarque : je ne l'ai pas encore utilisé et il peut y avoir des problèmes avec le compilateur Jack: voir ce rapport de bogue
la source
En Java, j'utiliserais le type facultatif de Guava . Étant un type réel, vous obtenez des garanties du compilateur sur son utilisation. Il est facile de le contourner et d'obtenir un
NullPointerException
, mais au moins la signature de la méthode communique clairement ce qu'elle attend en tant qu'argument ou ce qu'elle pourrait renvoyer.la source
java.util.Optional
place de la classe de Guava. Voir les notes / comparaison de Guava pour plus de détails sur les différences.Si vous utilisez Kotlin, il prend en charge ces annotations de nullabilité dans son compilateur et vous empêchera de passer un null à une méthode java qui nécessite un argument non nul. Même si cette question était à l'origine ciblée sur Java, je mentionne cette fonctionnalité Kotlin car elle est spécifiquement ciblée sur ces annotations Java et la question était "Y a-t-il un moyen de rendre ces annotations plus strictement appliquées et / ou de se propager davantage?" et cette fonctionnalité rend ces annotations plus strictement appliquées .
Classe Java utilisant l'
@NotNull
annotationClasse Kotlin appelant la classe Java et passant null pour l'argument annoté avec @NotNull
Erreur du compilateur Kotlin lors de l'application de l'
@NotNull
annotation.voir: http://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations
la source
myString.hashCode()
sera toujours lancer NPE même s'il@NotNull
n'est pas ajouté en paramètre. Alors, quoi de plus spécifique à propos de l'ajout?Depuis la nouvelle fonctionnalité Java 8 en option, vous ne devez plus utiliser @Nullable ou @Notnull dans votre propre code . Prenons l'exemple ci-dessous:
Il pourrait être réécrit avec:
L'utilisation d'une option vous oblige à vérifier la valeur nulle . Dans le code ci-dessus, vous ne pouvez accéder à la valeur qu'en appelant la
get
méthode.Un autre avantage est que le code devient plus lisible . Avec l'ajout de Java 9 ifPresentOrElse , la fonction pourrait même être écrite comme suit :
la source
Optional
, il existe encore de nombreuses bibliothèques et frameworks qui utilisent ces annotations de sorte qu'il n'est pas possible de mettre à jour / remplacer toutes vos dépendances par des versions mises à jour pour utiliser des options.Optional
peut toutefois aider dans les situations où vous utilisez null dans votre propre code.