aviso Findbugs: Igual método não deve assumir nada sobre o tipo de seu argumento
Pergunta
Ao executar FindBugs no meu projeto, eu tenho algumas instâncias do erro descrito acima.
Ou seja, minhas versões imperiosas de iguais converter o objeto RHS para o mesmo tipo como o objeto no qual a versão que prevalece é definido.
No entanto, eu não tenho certeza se um design melhor é possível, uma vez que AFAIK Java não permite variação dos parâmetros do método, por isso não é possível definir qualquer outro tipo para o parâmetro é igual a.
Estou fazendo algo muito errado, ou é FindBugs muito ansioso?
Uma maneira diferente de frase esta pergunta é: qual é o comportamento correto se o objeto passado para iguais não é do mesmo tipo que um LHS:? É este um falso, ou deveria haver uma exceção
Por exemplo:
public boolean equals(Object rhs)
{
MyType rhsMyType = (MyType)rhs; // Should throw exception
if(this.field1().equals(rhsMyType.field1())... // Or whatever
}
Solução
Normalmente, quando implementação iguais você pode verificar para ver se a classe do argumento é igual (ou compatível) para a classe de implementação antes de convertê-lo. Algo parecido com isto:
if (getClass() != obj.getClass())
return false;
MyObj myObj = (MyObj) obj;
Fazendo dessa forma, irá evitar que os FindBugs aviso.
Uma nota para tratar um comentário:
Algumas pessoas argumentam usar instanceof
vez de getClass
para verificar a segurança de tipos. Há um grande debate sobre isso, o que eu estava tentando não entrar em quando eu notar que você pode verificar pela igualdade classe ou compatibilidade, mas eu acho que não posso escapar. Tudo se resume a isso - se você usa instanceof
você pode apoiar a igualdade entre instâncias de uma classe e instâncias de sua subclasse, mas corre o risco de quebrar o contrato simétrica de equals
. Geralmente eu recomendo não usar instanceof
a menos que você sabe que você precisa e você sabe o que está fazendo. Para mais informações consulte:
- http://www.artima.com/weblogs/viewpost.jsp? thread = 4744
- Que questões devem ser consideradas ao substituir equals e hashCode em Java?
- http://www.macchiato.com/columns/Durable5.html
- http: // commons. apache.org/lang/api-release/org/apache/commons/lang/builder/EqualsBuilder.html (do Apache comum ajudante implementação)
- http://www.eclipsezone.com/eclipse/forums/t92613.rhtml (padrão do Eclipse é igual gerador)
- O NetBeans também gerador usa getClass ()
Outras dicas
Você provavelmente fazendo algo parecido com isto:
public class Foo {
// some code
public void equals(Object o) {
Foo other = (Foo) o;
// the real equals code
}
}
Neste exemplo você está assumindo algo sobre o argumento de equals (): Você está assumindo que é do tipo Foo. Isso não precisa ser o caso! Você também pode obter uma String (caso em que você deve quase definitivamente return false).
Assim, seu código deve ficar assim:
public void equals(Object o) {
if (!(o instanceof Foo)) {
return false;
}
Foo other = (Foo) o;
// the real equals code
}
(ou usar o getClass() != o.getClass()
mais rigorosas mencionado por Dave L.
Você também pode olhar para ele dessa forma:
Integer i = new Integer(42);
String s = "fourtytwo";
boolean b = i.equals(s);
Existe alguma razão para que este código deve jogar um ClassCastException
em vez de terminar normalmente e ajuste b
para false
?
Jogando um ClassCastException
como uma resposta a .equals()
não seria sensato. Porque mesmo que seja uma pergunta estúpida ( "É claro que uma String nunca é igual a um Foo!") Ainda é válida com uma resposta perfeitamente bem ( "não" == false
).
Eu recomendo ignorar disse aviso findbugs. Na prática, se iguais é chamado com um objeto de uma classe inesperada, é quase certamente um erro, e você quer falhar rapidamente sobre bugs.
Por exemplo, se você tem um 'arquivos ArrayList' e files.contains de chamadas ( "myfile.txt"), seria bom se você tem um ClassCastException. Em vez disso, Java apenas retorna falso, e ele provavelmente leva muito tempo até descobrir que o bug.
Eu começo meus iguais (Object) implementações como este:
if ((object == null) || !(object instaceof ThisClass)) {
return false;
}
Isto também irá evitar os FindBugs aviso, mas não voltará automaticamente false
quando uma subclasse de ThisClass está sendo entregue. Ele também pode ser considerado igual, especialmente se o seu método equals(Object)
não foi substituído.