Avertissement Findbugs: méthode Equals ne doit pas prendre quoi que ce soit sur le type de son argument

StackOverflow https://stackoverflow.com/questions/364454

  •  21-08-2019
  •  | 
  •  

Question

Lors de l'exécution FindBugs sur mon projet, je suis arrivé quelques cas de l'erreur décrite ci-dessus.

A savoir, mes versions impératives d'égal à égal Convertissez l'objet RHS dans le même type que l'objet dans lequel est défini la version primordiale.

Cependant, je ne sais pas si une meilleure conception est possible, car Java ne permet AFAIK pas la variance dans les paramètres de la méthode, il est donc impossible de définir un autre type pour le paramètre égal.

Ai-je fait quelque chose de très mal, ou est FindBugs trop impatient?

Une autre façon de formuler cette question est: quel est le comportement correct si l'objet est passé à égal n'est pas le même type comme LHS: Est-ce un faux, ou devrait-il y avoir une exception

?

Par exemple:

public boolean equals(Object rhs)
{
    MyType rhsMyType = (MyType)rhs; // Should throw exception
    if(this.field1().equals(rhsMyType.field1())... // Or whatever
}
Était-ce utile?

La solution

En règle générale, la mise en œuvre vous est égal pouvez vérifier si la classe de l'argument est égal (ou compatible) à la classe d'exécution avant de le jeter. Quelque chose comme ceci:

if (getClass() != obj.getClass())
    return false;
MyObj myObj = (MyObj) obj;

En procédant ainsi, empêchera l'avertissement FindBugs.

Une note de côté pour répondre à un commentaire:
Certaines personnes affirment utiliser au lieu de instanceof pour vérifier la sécurité getClass de type. Il y a un grand débat à ce sujet, que je tentais de ne pas entrer dans quand je remarquai que vous pouvez vérifier l'égalité des classes ou compatibilité, mais je suppose que je ne peux pas y échapper. Il se résume à ceci - si vous utilisez, vous pouvez soutenir equals l'égalité entre les instances d'une classe et les instances de sa sous-classe, mais vous risquez de rompre le contrat symétrique de <=>. En général, je recommande de ne pas utiliser sauf si vous savez <=> vous en avez besoin et vous savez ce que vous faites. Pour en savoir plus, voir l'information:

Autres conseils

Vous faites probablement quelque chose comme ceci:

public class Foo {
  // some code

  public void equals(Object o) {
    Foo other = (Foo) o;
    // the real equals code
  }
}

Dans cet exemple, vous assumez quelque chose sur l'argument d'égal à égal (): Vous assumez c'est de type Foo. Ce ne sera pas nécessairement le cas! Vous pouvez également obtenir une chaîne (dans ce cas, vous devriez presque revenir définitivement faux).

Alors votre code devrait ressembler à ceci:

public void equals(Object o) {
  if (!(o instanceof Foo)) {
    return false;
  }
  Foo other = (Foo) o;
  // the real equals code
}

(ou utilisez le plus rigoureux mentionné par Dave getClass() != o.getClass() L.

Vous pouvez aussi regarder cette façon:

Integer i = new Integer(42);
String s = "fourtytwo";
boolean b = i.equals(s);

Y at-il raison que ce code devrait jeter un lieu de terminer ClassCastException normalement et la mise à b false?

Lancer une en réponse .equals() à ne serait pas <=> raisonnable. Parce que même si elle est une question stupide ( « Bien sûr, une chaîne est jamais égale à un Foo! »), Il est encore valide une réponse parfaitement bien ( « non » == <=>).

Je vous recommande d'ignorer ces avertissements findbugs. En pratique, si Égale est appelée avec un objet d'une classe inattendue, il est presque certainement un bug, et que vous voulez à l'échec rapide sur les bugs.

Par exemple, si vous avez un « fichiers ArrayList » et appelez files.contains ( « MonFichier.txt »), ce serait bien si vous avez un ClassCastException. Au lieu de cela, Java retourne simplement faux, et il faut sans doute depuis longtemps jusqu'à ce que vous découvrez ce bogue.

Je commence mes equals (Object) mises en œuvre comme ceci:

if ((object == null) || !(object instaceof ThisClass)) {
    return false;
}

Cela permettra également d'éviter l'avertissement FindBugs mais ne reviendra pas automatiquement quand une sous-classe false de ThisClass est remis. Il peut également être considéré comme égal, surtout si la méthode n'a pas été equals(Object) substituée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top