Java constructeur style: vérifiez les paramètres ne sont pas null
Quelles sont les meilleures pratiques si vous avez une classe qui accepte certains paramètres, mais aucun d'entre eux sont autorisés à être null
?
La suite est évidente, mais l'exception est un peu imprécise:
public class SomeClass
{
public SomeClass(Object one, Object two)
{
if (one == null || two == null)
{
throw new IllegalArgumentException("Parameters can't be null");
}
//...
}
}
Ici les exceptions permettent de savoir quel paramètre est null, mais le constructeur est maintenant assez laid:
public class SomeClass
{
public SomeClass(Object one, Object two)
{
if (one == null)
{
throw new IllegalArgumentException("one can't be null");
}
if (two == null)
{
throw new IllegalArgumentException("two can't be null");
}
//...
}
Ici, le constructeur est plus lisible, mais maintenant, le code du constructeur n'est pas vraiment dans le constructeur:
public class SomeClass
{
public SomeClass(Object one, Object two)
{
setOne(one);
setTwo(two);
}
public void setOne(Object one)
{
if (one == null)
{
throw new IllegalArgumentException("one can't be null");
}
//...
}
public void setTwo(Object two)
{
if (two == null)
{
throw new IllegalArgumentException("two can't be null");
}
//...
}
}
Lequel de ces styles est le meilleur?
Ou est-il une alternative qui est plus largement acceptée?
- Je recommande numéro 2. Juste parce qu'il semble laid ne signifie pas qu'il n'est pas bon. Souvenez-vous de code est pour l'homme à lire et à comprendre non pas des machines.
- La différence de comportement entre la deuxième et la troisième approche est assez importante, à jamais répondre à cette question de façon raisonnable. Le second permet de les valeurs à définir à
null
par la suite par les organismes de normalisation. Si vous voulez cohérente de comportement, alors vous devez en aucune façon aller pour 3, ce n'est pas un problème du style plus. - qui suppose que les deux 2 et 3 ont les setters. Si les 2 n'ont pas de setter puis c'est essentiellement le même que 3; à l'exception de l'utilisateur peut définir l'objet après la création de l'objet.
Vous devez vous connecter pour publier un commentaire.
De la deuxième ou de la troisième.
Car elle indique à l'utilisateur de votre API exactement ce qui est allé mal.
Pour les moins de verbosité utilisation
Validate.notNull(obj, message)
de commons-lang. Ainsi, votre constructeur va ressembler:Plaçant le vérifier dans le setter est également acceptable, avec le même niveau de verbosité commentaire. Si votre setters ont aussi le rôle de la préservation de l'objet de cohérence, vous pouvez choisir la troisième en tant que bien.
null
valeurs puis j'avais l'impression que c'est un bug si le setter accepte.Vous pouvez utiliser l'une des nombreuses bibliothèques conçues pour faciliter condition préalable vérifie. Beaucoup de code dans Google Goyave utilise
com.google.commun.de la base.Conditions préalables
Il a
checkNotNull
qui est largement utilisé dans de Goyave. Vous pouvez alors écrire:La plupart des méthodes sont surchargées soit de prendre un pas de message d'erreur, une correction du message d'erreur, ou un templatized message d'erreur avec varargs.
Sur
IllegalArgumentException
vsNullPointerException
Pendant que votre code d'origine jette
IllegalArgumentException
surnull
arguments, la Goyave estPreconditions.checkNotNull
jetteNullPointerException
à la place.Voici une citation de Efficace Java 2nd Edition: Article 60: Favoriser l'utilisation de la norme exceptions:
Un
NullPointerException
n'est pas réservée seulement lorsque vous accédez à des membres d'unenull
de référence; c'est assez standard pour les jeter quand un argument estnull
quand c'est une valeur illégale.null
, et des NPE dit que les applications peuvent utiliser pour "d'autres illégale denull
".Object.requireNonNull
introduite dans le JDK 7 jette également unNullPointerException
, il semble donc que la Guerre Sainte est bel et bien fini.Vieille question; une nouvelle réponse (déjà mentionné dans un autre commentaire, mais je pense que vaut sa propre réponse).
Java 7
java.lang.Objects.requireNonNull()
à l'Api, tout le monde peut utiliser. Si la vérification de tous les arguments pour les nuls se résume à une courte liste comme:Notes:
J'aurais une méthode utilitaire:
Je l'aurais retour de l'objet, de sorte que vous pouvez l'utiliser dans des tâches comme ceci:
EDIT: en ce qui Concerne les suggestions pour utiliser une bibliothèque tierce, le Google des conditions Préalables, en particulier, le ci-dessus, même mieux que mon code. Cependant, si c'est la seule raison d'inclure la librairie dans votre projet, je serais hésitant. La méthode est trop simple.
Objects.notNull
est proposé pour JDK7.Outre les réponses données ci-dessus, qui sont toutes valables et raisonnables, je pense qu'il est bon de souligner que, peut-être la vérification de la valeur null n'est pas nécessaire de "bonne pratique". (En supposant que les lecteurs autres que l'OP peut prendre la question dogmatique)
De Misko Hevery blog sur la testabilité:
Pour Affirmer ou De ne Pas faire Valoir
Comparaison des Façons de Vérifier les conditions Préalables à Java - Goyave vs Apache Commons vs Spring Framework vs Plaine Java Affirme
c'est le résumé de cet article:
http://www.sw-engineering-candies.com/blog-1/comparison-of-ways-to-check-preconditions-in-java
Une alternative à jeter un décoché exception serait l'utilisation de
assert
. Sinon, l'Id de jeter checked exceptions pour faire de l'appelant conscients du fait que le constructeur ne fonctionnera pas avec des valeurs illégales.La différence entre vos deux premières solutions avez-vous besoin d'un message d'erreur détaillé, avez-vous besoin de savoir quel est le paramètre qui a échoué ou est-ce assez pour savoir que l'instance n'aurait pas pu être créé en raison d'illégal arguments?
Remarque, que les deuxième et troisième exemple ne peut pas en compte correctement des deux paramètres ont été nulles.
BTW - je vote pour une variation de (1):
Les Annotations pour l'analyse statique sont également utiles, que ce soit en plus ou en-place-de l'exécution des contrôles.
FindBugs, par exemple, fournit un @Non annotation.
Vous pouvez tout simplement avoir une méthode qui prend tous les arguments du constructeur que vous avez besoin pour valider. Cette méthode lève une exception avec un message spécifique en fonction dont l'argument n'est pas valide.
Votre constructeur appelle cette méthode, et si elle passe, elle initialiser des valeurs.
Je suppose que vous parlez de la construction dans le
assert
en Java. À mon avis, il n'est pas vraiment une bonne idée de l'utiliser. Car il peut être activée/désactivée à l'aide de paramètres de ligne de commande. Par conséquent, certains disent que c'est seulement acceptable pour une utilisation dans des méthodes privées.Mes mentors me disent de ne pas ré-inventer la roue! Leur avis est d'utiliser les bibliothèques. Ils sont (probablement) bien conçus et testés. Bien sûr, il est de votre responsabilité de vous assurer que vous prenez un bon bibliothèque de qualité.
D'autres me disent que l'Entreprise ppl - dans certaines conditions -, sont fausses et vous introduire plus de la dépendance pour les tâches simples que nécessaire. Je peux accepter que point trop... Mais voici ma dernière expérience:
D'abord j'ai écrit ma propre méthode pour vérifier les paramètres nuls. C'est ennuyeux et redondant. Je sais que je devrais le mettre dans une classe Utilitaire. Mais pourquoi dois-je l'écrire à la première place, quand quelqu'un a déjà fait ça? Je peux gagner du temps pas de l'écriture de l'unité de test et de conception d'un contenu existant. Sauf si vous voulez faire de l'exercice ou de savoir que je ne recommande pas de le faire.
J'ai récemment commencé à utiliser google goyave et je trouve qu'avec apache commons - une fois que vous commencez à les utiliser, vous ne l'utilisez pas pour ça, une seule méthode. Vous pourrez les découvrir et les utiliser de plus en plus. À la fin, ce sera de rendre votre code plus court, plus lisible, plus cohérente et plus maintenable.
BTW.: En fonction de vos objectifs, j'irais avec 2 ou 3 à l'aide de l'un de la bibliothèque ci-dessus...