77 votes

Est-ce une mauvaise idée si equals(null) throws exception NullPointerException à la place?

Le contrat d' equals concernant null, est comme suit:

Pour tout non-nulle de la valeur de référence x, x.equals(null) doit return false.

C'est plutôt étrange, car si o1 != null et o2 == null, alors nous avons:

o1.equals(o2) // returns false
o2.equals(o1) // throws NullPointerException

Le fait qu' o2.equals(o1) throws NullPointerException est une bonne chose, car il nous alerte d'erreur du développeur. Et pourtant, cette erreur ne serait pas atteint si, pour diverses raisons, nous avons tout juste de passer à d' o1.equals(o2), ce qui serait tout simplement "en silence l'échec" à la place.

Donc les questions sont:

  • Pourquoi est-ce une bonne idée que o1.equals(o2) doit return false au lieu de jeter NullPointerException?
  • Serait-ce une mauvaise idée si dans la mesure du possible, nous réécrire le contrat de sorte qu' anyObject.equals(null) toujours jeter NullPointerException à la place?

Sur la comparaison avec d' Comparable

En revanche, c'est ce que l' Comparable contrat dit:

Notez que null n'est pas une instance de classe, et e.compareTo(null) jette NullPointerException même si e.equals(null) retours false.

Si NullPointerException est approprié pour compareTo, pourquoi n'est-il pas pour equals?

Questions connexes


Purement semantical argument

Ce sont les mots réels en Object.equals(Object obj) documentation:

Indique si quelque autre objet est "égal" à celui-ci.

Et qu'est ce qu'un objet?

JLS 4.3.1 Objets

Un objet est une instance de classe ou d'un tableau.

Les valeurs de référence (souvent juste références) sont des pointeurs sur ces objets, et un spécial null de référence, qui fait référence à aucun objet.

Mon argument à partir de cet angle est vraiment simple.

  • equals teste si quelque autre objet est "égal" this
  • null de référence ne donne pas d' autre objet pour le test
  • Par conséquent, equals(null) devraient jeter NullPointerException

108voto

Sean Owen Points 36577

À la question de savoir si cette asymétrie est incompatible, je ne crois pas, et je vous renvoie à cette ancienne Zen ko-an:

  • Demandez à n'importe quel homme si il est aussi bon que l'homme à côté et chacun va dire oui.
  • Demandez à n'importe quel homme si il est aussi bon en tant que personne, et chacun dira non.
  • Demander à personne si c'est aussi bon que n'importe quel homme, et vous ne serez jamais obtenir une réponse.

À ce moment, le compilateur a atteint l'illumination.

19voto

duffymo Points 188155

Une exception ne devrait vraiment être d'une exceptionnelle situation. Un pointeur null peut-être pas une erreur du développeur.

Vous avez cité le contrat existant. Si vous décidez d'aller à l'encontre de la convention, après tout ce temps, où chaque développeur Java attend égale de fausse déclaration, vous allez faire quelque chose d'inattendu et indésirable qui feront de votre classe un paria.

Je pourrais pas être plus en désaccord. Je ne voudrais pas de réécriture est égal à lever une exception tous les temps. J'avais remplacé toute la classe qui fait que si j'étais son client.

8voto

Angus Points 91

Pensez à comment .égale est liée à l' == et .compareTo est liée pour les opérateurs de comparaison >, <, >=, <=.

Si vous allez affirment que l'utilisation de .est égal à comparer un objet à null devriez jeter un NPE, alors que vous auriez à dire que ce code devrait lancer un:

Object o1 = new Object();
Object o2 = null;
boolean b = (o1 == o2); // should throw NPE here!

La différence entre o1.equals(o2) et o2.equals(o1) est que dans le premier cas, vous êtes en comparant quelque chose à null, semblable à o1 == o2, alors que dans le second cas, la méthode equals est jamais réellement exécutées donc il n'y a pas de comparaison qui se passe à tous.

Concernant l' .compareTo contrat, la comparaison d'un objet non-null avec un objet nul, c'est comme essayer de faire ceci:

int j = 0;
if(j > null) { 
   ... 
}

Évidemment, cela ne compile pas. Vous pouvez utiliser la fonction auto-unboxing pour faire de la compilation, mais vous obtenez un NPE quand vous faites la comparaison, ce qui est cohérent avec la .compareTo contrat:

Integer i = null;
int j = 0;
if(j > i) { // NPE
   ... 
}

4voto

DaveJohnston Points 5475

Non que ce soit impérativement une réponse à votre question, c'est juste un exemple, quand je trouve qu'il est utile que le comportement est de savoir comment il est maintenant.

private static final String CONSTANT_STRING = "Some value";
String text = getText();  // Whatever getText() might be, possibly returning null.

Comme il se trouve que je peux faire.

if (CONSTANT_STRING.equals(text)) {
    // do something.
}

Et je n'ai aucune chance d'obtenir un NullPointerException. Si elle était modifiée comme vous l'avez suggéré, je serais de retour à avoir à le faire:

if (text != null && text.equals(CONSTANT_STRING)) {
    // do something.
}

Est-ce une raison suffisante pour que le comportement soit ce qu'il est?? Je ne sais pas, mais il est utile d'effets secondaires.

4voto

arg20 Points 1020

Si vous prenez des concepts orientés objet en compte, et de considérer l'ensemble de l'expéditeur et du destinataire rôles, je dirais que le comportement est pratique. Voir dans le premier cas, vous demandez à un objet si il est égal à personne. Il DEVRAIT dire "NON, je ne suis pas".

Dans le second cas, vous n'avez pas de référence à toute personne, Donc vous n'êtes pas vraiment demander à quelqu'un. CELA devrait lancer une exception, le premier cas il ne faut pas.

Je pense que c'est seulement asymétrique si vous oubliez au sujet de l'orientation de l'objet et de traiter l'expression comme une égalité mathématique. Toutefois, dans ce paradigme, les deux extrémités de jouer différents rôles, il est attendu que l'ordre des questions.

Comme un point final. Un null pointer exception doit être soulevée quand il ya une erreur dans votre code. Cependant, de Demander un objet si il est personne, ne devrait pas être considéré comme une faille de programmation. Je pense que c'est tout à fait normal de demander à un objet s'il n'est pas null. Que faire si vous n'avez pas le contrôle de la source qui fournit vous avec l'objet? et cette source vous envoie la valeur null. Voulez-vous vérifier si l'objet est null, et seulement par la suite voir si ils sont égaux? Ne serait-il pas plus intuitif et il suffit de comparer les deux et quel que soit le deuxième objet est la comparaison sera effectuée sans exceptions?

En toute honnêteté, je serais énervé si une méthode equals à l'intérieur de son corps renvoie une exception de pointeur null. Égale est destiné à être utilisé contre toute sorte d'objet, de sorte qu'il ne devrait pas être si pointilleux sur ce qu'il reçoit. Si une méthode equals retourné npe, la dernière chose sur mon esprit serait qu'il le faisait exprès. Spécialement étant donné que c'est un décoché exception. SI vous n'avez soulever une npe un gars aurait à n'oubliez pas de toujours vérifier la valeur null avant d'appeler votre méthode, ou pire encore, entourent l'appel à égal dans un bloc try/catch (Dieu que je déteste les blocs try/catch) Mais bon...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X