Qual é a diferença entre ==e .equals()no Scala e quando usar qual?
A implementação é a mesma que em Java?
EDIT: A pergunta relacionada fala sobre casos específicos de AnyVal. O caso mais geral é Any.
Qual é a diferença entre ==e .equals()no Scala e quando usar qual?
A implementação é a mesma que em Java?
EDIT: A pergunta relacionada fala sobre casos específicos de AnyVal. O caso mais geral é Any.
Respostas:
Você normalmente usa ==, ele direciona para equals, exceto que o trata nullcorretamente. Igualdade de referência (raramente usada) é eq.
3 == BigInt(3)e BigInt(3) == 3são verdadeiros. Mas, 3.equals(BigInt(3))é falso, enquanto BigInt(3).equals(3)é verdade. Portanto, prefira usar ==. Evite usar equals()na Scala. Eu acho ==que a conversão implícita bem, mas equals()não.
new java.lang.Integer(1) == new java.lang.Double(1.0)é verdade enquanto new java.lang.Integer(1) equals new java.lang.Double(1.0)é falso?
equalsmétodo para comparar o conteúdo de cada instância. Este é o mesmo equalsmétodo usado em Java==operador para comparar, sem se preocupar com nullreferênciaseqmétodo para verificar se os dois argumentos são EXATAMENTE a mesma referência. É recomendável não usar, a menos que você entenda como isso funciona e, muitas vezes equals, funcionará para o que você precisa. E certifique-se de usar isso apenas com AnyRefargumentos, não apenasAnyNOTA: No caso de equals, assim como em Java, ele pode não retornar o mesmo resultado se você alternar os argumentos, por exemplo 1.equals(BigInt(1)), retornará para falseonde o inverso retornará true. Isso ocorre porque cada implementação verifica apenas tipos específicos. Números primitivos não verificam se o segundo argumento é de Numbernem BigInttipos, mas apenas de outros tipos primitivos
O AnyRef.equals(Any)método é substituído por subclasses. Um método da Especificação Java que também chegou ao Scala. Se usado em uma instância sem caixa, é incluído na caixa para chamar isso (embora oculto no Scala; mais óbvio no Java com int-> Integer). A implementação padrão apenas compara referências (como em Java)
O Any.==(Any)método compara dois objetos e permite que qualquer argumento seja nulo (como se estivesse chamando um método estático com duas instâncias). Ele compara se os dois são nulle chama o equals(Any)método na instância em caixa.
O AnyRef.eq(AnyRef)método compara apenas referências, é onde a instância está localizada na memória. Não há boxe implícito para esse método.
1 equals 2retornará false, pois ele redireciona paraInteger.equals(...)1 == 2retornará false, pois ele redireciona paraInteger.equals(...)1 eq 2 não será compilado, pois exige que ambos os argumentos sejam do tipo AnyRefnew ArrayList() equals new ArrayList()retornará true, pois verifica o conteúdonew ArrayList() == new ArrayList()retornará true, pois ele redireciona paraequals(...)new ArrayList() eq new ArrayList()retornará false, pois os dois argumentos são instâncias diferentesfoo equals fooretornará true, a menos que fooseja null, então lançará umNullPointerExceptionfoo == fooretornará true, mesmo que foosejanullfoo eq fooretornará true, pois os dois argumentos apontam para a mesma referênciaHá uma diferença interessante entre ==e equalspara Floate Doubletipos: Eles tratam de maneira NaNdiferente:
scala> Double.NaN == Double.NaN
res3: Boolean = false
scala> Double.NaN equals Double.NaN
res4: Boolean = true
Edit: Como foi apontado em um comentário - "isso também acontece em Java" - depende do que exatamente é isso :
public static void main(final String... args) {
final double unboxedNaN = Double.NaN;
final Double boxedNaN = Double.valueOf(Double.NaN);
System.out.println(unboxedNaN == unboxedNaN);
System.out.println(boxedNaN == boxedNaN);
System.out.println(boxedNaN.equals(boxedNaN));
}
Isso imprimirá
false
true
true
Portanto, o unboxedNanrendimento é falsecomparado à igualdade, porque é assim que os números de ponto flutuante do IEEE o definem e isso deve realmente acontecer em todas as linguagens de programação (embora, de alguma forma, mexa com a noção de identidade).
O NaN em caixa rende true para a comparação usando ==em Java, pois estamos comparando referências de objetos.
Eu não tenho uma explicação para o equalscaso, IMHO realmente deve se comportar da mesma forma que ==em valores duplos sem caixa, mas não.
Traduzido para Scala, o assunto é um pouco mais complicado, pois Scala unificou tipos primitivos e de objetos Anye se traduz no duplo primitivo e no duplo em caixa, conforme necessário. Assim, o scala ==aparentemente se resume a uma comparação de NaNvalores primitivos , mas equalsusa o definido nos valores Double em caixa (há muita mágica de conversão implícita em andamento e há coisas adicionadas em dobro por RichDouble).
Se você realmente precisa descobrir se algo realmente é NaNusado isNaN: