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
.
scala
equality
scala-java-interop
Jus12
fonte
fonte
Respostas:
Você normalmente usa
==
, ele direciona paraequals
, exceto que o tratanull
corretamente. Igualdade de referência (raramente usada) éeq
.fonte
3 == BigInt(3)
eBigInt(3) == 3
são verdadeiros. Mas,3.equals(BigInt(3))
é falso, enquantoBigInt(3).equals(3)
é verdade. Portanto, prefira usar==
. Evite usarequals()
na Scala. Eu acho==
que a conversão implícita bem, masequals()
não.new java.lang.Integer(1) == new java.lang.Double(1.0)
é verdade enquantonew java.lang.Integer(1) equals new java.lang.Double(1.0)
é falso?==
é um método final e chama.equals
, que não é final.Isso é radicalmente diferente do Java, onde
==
é um operador e não um método e compara estritamente a igualdade de referência para objetos.fonte
TL; DR
equals
método para comparar o conteúdo de cada instância. Este é o mesmoequals
método usado em Java==
operador para comparar, sem se preocupar comnull
referênciaseq
mé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 vezesequals
, funcionará para o que você precisa. E certifique-se de usar isso apenas comAnyRef
argumentos, não apenasAny
NOTA: No caso de
equals
, assim como em Java, ele pode não retornar o mesmo resultado se você alternar os argumentos, por exemplo1.equals(BigInt(1))
, retornará parafalse
onde 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 é deNumber
nemBigInt
tipos, mas apenas de outros tipos primitivosDetalhes
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 comint
->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ãonull
e chama oequals(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.Exemplos
1 equals 2
retornaráfalse
, pois ele redireciona paraInteger.equals(...)
1 == 2
retornaráfalse
, pois ele redireciona paraInteger.equals(...)
1 eq 2
não será compilado, pois exige que ambos os argumentos sejam do tipoAnyRef
new 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 foo
retornarátrue
, a menos quefoo
sejanull
, então lançará umNullPointerException
foo == foo
retornarátrue
, mesmo quefoo
sejanull
foo eq foo
retornarátrue
, pois os dois argumentos apontam para a mesma referênciafonte
Há uma diferença interessante entre
==
eequals
paraFloat
eDouble
tipos: Eles tratam de maneiraNaN
diferente:Edit: Como foi apontado em um comentário - "isso também acontece em Java" - depende do que exatamente é isso :
Isso imprimirá
Portanto, o
unboxedNan
rendimento éfalse
comparado à 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
equals
caso, 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
Any
e se traduz no duplo primitivo e no duplo em caixa, conforme necessário. Assim, o scala==
aparentemente se resume a uma comparação deNaN
valores primitivos , masequals
usa o definido nos valores Double em caixa (há muita mágica de conversão implícita em andamento e há coisas adicionadas em dobro porRichDouble
).Se você realmente precisa descobrir se algo realmente é
NaN
usadoisNaN
:fonte
Em Scala ==, primeiro verifique os valores Nulos e, em seguida, chama o método equals no primeiro objeto
fonte