aviso Findbugs: Igual método não deve assumir nada sobre o tipo de seu argumento

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

  •  21-08-2019
  •  | 
  •  

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
}
Foi útil?

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:

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top