Jaka jest różnica między ==
i .equals()
w Scala, a kiedy używać które?
Czy implementacja jest taka sama jak w Javie?
EDYCJA: Powiązane pytanie dotyczy konkretnych przypadków AnyVal
. Bardziej ogólny przypadek to Any
.
Jaka jest różnica między ==
i .equals()
w Scala, a kiedy używać które?
Czy implementacja jest taka sama jak w Javie?
EDYCJA: Powiązane pytanie dotyczy konkretnych przypadków AnyVal
. Bardziej ogólny przypadek to Any
.
Odpowiedzi:
Zwykle używasz
==
, kieruje doequals
, z wyjątkiem tego, że traktuje jenull
poprawnie. Równość odwołań (rzadko używana) toeq
.źródło
3 == BigInt(3)
iBigInt(3) == 3
są prawdziwe. Ale3.equals(BigInt(3))
jest fałszywe, podczas gdyBigInt(3).equals(3)
jest prawdziwe. Dlatego wolę używać==
. Unikaj używaniaequals()
w scali. Myślę, że==
niejawna konwersja dobrzeequals()
działa , ale tak nie jest.new java.lang.Integer(1) == new java.lang.Double(1.0)
jest prawdziwe, podczas gdynew java.lang.Integer(1) equals new java.lang.Double(1.0)
jest fałszywe?==
jest ostateczną metodą, a wywołania.equals
, które nie są ostateczne.Jest to radykalnie inne niż Java, gdzie
==
jest operatorem, a nie metodą i ściśle porównuje równość odwołań dla obiektów.źródło
TL; DR
equals
, aby porównać zawartość każdego wystąpienia. To ta samaequals
metoda, która jest używana w Javie==
operatora do porównania, nie martwiąc się onull
odwołaniaeq
metody, aby sprawdzić, czy oba argumenty są DOKŁADNIE tym samym odwołaniem. Zaleca się, aby nie używać, chyba że rozumiesz, jak to działa i częstoequals
będzie działać w przypadku tego, czego potrzebujesz. I upewnij się, że używasz tego tylko zAnyRef
argumentami, a nie tylkoAny
UWAGA: W przypadku
equals
, tak jak w Javie, może nie zwrócić tego samego wyniku, jeśli zmienisz argumenty, np.1.equals(BigInt(1))
Zwrócifalse
tam, gdzie zwróci odwrotnośćtrue
. Dzieje się tak, ponieważ każda implementacja sprawdza tylko określone typy. Liczby pierwotne nie sprawdzają, czy drugi argument jest typuNumber
nor,BigInt
ale tylko innych typów pierwotnychDetale
AnyRef.equals(Any)
Metoda jest jedną zastąpione przez podklasy. Metoda ze specyfikacji Java, która również trafiła do Scali. Jeśli jest używany w instancji bez opakowania, jest zaznaczony, aby to wywołać (choć ukryty w Scali; bardziej oczywiste w Javie zint
->Integer
). Domyślna implementacja jedynie porównuje referencje (jak w Javie)Any.==(Any)
Sposób porównuje dwa przedmioty i pozwala oba argumenty będą puste (jak wywołanie statyczne metody z dwóch przypadkach). Porównuje, jeśli oba sąnull
, a następnie wywołujeequals(Any)
metodę w pudełkowej instancji.AnyRef.eq(AnyRef)
Sposób porównuje tylko odniesienia, to jest, gdy przykład znajduje się w pamięci. W przypadku tej metody nie ma niejawnego boksu.Przykłady
1 equals 2
powrócifalse
, ponieważ przekierowuje doInteger.equals(...)
1 == 2
powrócifalse
, ponieważ przekierowuje doInteger.equals(...)
1 eq 2
nie skompiluje się, ponieważ wymaga, aby oba argumenty były typuAnyRef
new ArrayList() equals new ArrayList()
zwrócitrue
, ponieważ sprawdza zawartośćnew ArrayList() == new ArrayList()
powrócitrue
, ponieważ przekierowuje doequals(...)
new ArrayList() eq new ArrayList()
zwrócifalse
, ponieważ oba argumenty są różnymi wystąpieniamifoo equals foo
zwrócitrue
, chyba żefoo
jestnull
, a następnie wyrzuciNullPointerException
foo == foo
powrócitrue
, nawet jeślifoo
jestnull
foo eq foo
zwróci wartośćtrue
, ponieważ oba argumenty prowadzą do tego samego odwołaniaźródło
Istnieje interesująca różnica między typami
==
iequals
dlaFloat
orazDouble
: traktują oneNaN
inaczej:Edit: Jak wskazano w komentarzu - „tak się dzieje również w Javie” - zależy od tego, co dokładnie to jest:
To się wydrukuje
Tak więc
unboxedNan
wydajnośćfalse
porównana pod kątem równości, ponieważ tak definiują ją liczby zmiennoprzecinkowe IEEE i powinno to naprawdę mieć miejsce w każdym języku programowania (chociaż w jakiś sposób miesza się z pojęciem tożsamości).Pole NaN daje wartość true dla porównania używanego
==
w Javie, gdy porównujemy odwołania do obiektów.Nie mam wytłumaczenia dla
equals
sprawy, IMHO to naprawdę powinno zachowywać się tak samo jak==
na unboxed double wartości, ale tak nie jest.W tłumaczeniu na Scala sprawa jest trochę bardziej skomplikowana, ponieważ Scala ujednolicił typy prymitywne i obiektowe na
Any
i tłumaczy na prymitywne podwójne i pudełkowe podwójne w razie potrzeby. Tak więc skala==
najwyraźniej sprowadza się do porównaniaNaN
wartości pierwotnych , aleequals
wykorzystuje tę zdefiniowaną na opakowanych wartościach Double (dzieje się wiele niejawnej magii konwersji i jest coś podwojonego przez podwójneRichDouble
).Jeśli naprawdę chcesz się dowiedzieć, czy coś jest rzeczywiście
NaN
używaneisNaN
:źródło
W Scala == najpierw sprawdź wartości Null , a następnie wywołuje metodę equals na pierwszym obiekcie
źródło