warning Findbugs: Equals metodo non deve dare per scontato nulla circa il tipo del suo argomento

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

  •  21-08-2019
  •  | 
  •  

Domanda

Quando si esegue FindBugs sul mio progetto, ho avuto un paio di casi di l'errore descritto in precedenza.

Vale a dire, le mie versioni imperativi di pari cast dell'oggetto RHS nello stesso tipo come l'oggetto in cui è definito la versione prevalente.

Tuttavia, non sono sicuro se un disegno migliore è possibile, dal momento che per quanto ne so Java non consente la varianza dei parametri di metodo, per cui non è possibile definire qualsiasi altro tipo per l'uguale parametro.

sto facendo qualcosa di molto sbagliato, o è FindBugs troppo ansiosi?

Un modo diverso per frase questa domanda è: qual è il comportamento corretto se l'oggetto passato al uguale non è dello stesso tipo di un LHS: Si tratta di un falso, o ci dovrebbe essere un'eccezione

?

Ad esempio:

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

Soluzione

In genere, in sede di attuazione uguale è possibile controllare per vedere se la classe l'argomento è uguale (o compatibile) per la classe che implementa prima del getto di esso. Qualcosa di simile a questo:

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

Facendo in questo modo impedirà l'avviso FindBugs.

Una nota a margine per affrontare un commento:
Alcune persone sostengono di usare instanceof invece di getClass per verificare la sicurezza di tipo. C'è un grande dibattito su quello che stavo cercando di non entrare in quando ho notato che è possibile controllare per l'uguaglianza di classe o la compatibilità, ma credo che non posso sfuggire. Si riduce a questo - se si utilizza equals si può sostenere l'uguaglianza tra le istanze di una classe e le istanze della sua sottoclasse, ma si rischia di rompere il contratto simmetrica di <=>. In generale mi sento di raccomandare di non usare <=> se non si sa ne avete bisogno e si sa cosa si sta facendo. Per ulteriori informazioni:

Altri suggerimenti

Probabilmente stai facendo qualcosa di simile a questo:

public class Foo {
  // some code

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

In questo esempio si stanno assumendo qualcosa circa l'argomento di equals (): si stanno assumendo è di tipo Foo. Questo non deve necessariamente essere il caso! È inoltre possibile ottenere una stringa (nel qual caso si dovrebbe quasi sicuramente falsa).

Quindi, il codice dovrebbe essere simile a questo:

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

(o utilizzare il più rigoroso getClass() != o.getClass() menzionato da Dave L.

Si potrebbe anche guardare in questo modo:

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

C'è un motivo che questo codice dovrebbe lanciare una ClassCastException invece di finire normalmente e impostazione b a false?

Lanciare una .equals() come risposta a <=> non sarebbe sensato. Perché anche se si tratta di una domanda stupida ( "Certo che una stringa non è mai uguale ad un Foo!") È ancora uno valido con una risposta perfettamente bene ( "no" == <=>).

Mi consiglia di ignorare dette findbugs avvertimento. In pratica, se è uguale viene chiamato con un oggetto di una classe inatteso, è quasi certamente un bug, e si vuole fallire veloce su bug.

Ad esempio, se si dispone di un 'file' ArrayList e chiamare files.contains ( "myfile.txt"), sarebbe bello se hai un ClassCastException. Invece, Java restituisce solo falso, ed è probabile che richiede molto tempo fino a quando si scopre che bug.

mi metto i miei Equals (Object) implementazioni in questo modo:

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

Questo eviterà anche l'avvertimento FindBugs ma non ritorna automaticamente false quando una sottoclasse di ThisClass viene consegnata. Potrebbe anche essere considerati uguali, soprattutto se il suo metodo equals(Object) non è stata sostituita.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top