Was ist der Unterschied zwischen ==
und .equals()
in Scala und wann welche zu verwenden?
Ist die Implementierung dieselbe wie in Java?
EDIT: Die verwandte Frage spricht über bestimmte Fälle von AnyVal
. Der allgemeinere Fall ist Any
.
Was ist der Unterschied zwischen ==
und .equals()
in Scala und wann welche zu verwenden?
Ist die Implementierung dieselbe wie in Java?
EDIT: Die verwandte Frage spricht über bestimmte Fälle von AnyVal
. Der allgemeinere Fall ist Any
.
Antworten:
Normalerweise verwendet
==
es Routen zuequals
, außer dass esnull
s richtig behandelt . Referenzgleichheit (selten verwendet) isteq
.quelle
3 == BigInt(3)
undBigInt(3) == 3
wahr sind. Aber3.equals(BigInt(3))
ist falsch, währendBigInt(3).equals(3)
es wahr ist. Verwenden Sie daher lieber==
. Vermeiden Sie die Verwendungequals()
in Scala. Ich denke==
, implizite Konvertierung ist gut, aberequals()
nicht.new java.lang.Integer(1) == new java.lang.Double(1.0)
ist wahr, währendnew java.lang.Integer(1) equals new java.lang.Double(1.0)
falsch ist?==
ist eine endgültige Methode und ruft auf.equals
, was nicht endgültig ist.Dies unterscheidet sich grundlegend von Java, bei dem
==
es sich eher um einen Operator als um eine Methode handelt und die Referenzgleichheit für Objekte streng verglichen wird.quelle
TL; DR
equals
Methode überschreiben , um den Inhalt jeder Instanz zu vergleichen. Dies ist die gleicheequals
Methode wie in Java==
Operator zum Vergleichen, ohne sich umnull
Referenzen kümmern zu müsseneq
Methode, um zu überprüfen, ob beide Argumente genau dieselbe Referenz sind. Empfohlen, nicht zu verwenden, es sei denn, Sie verstehen, wie dies funktioniert, und funktionieren häufigequals
für das, was Sie stattdessen benötigen. Und stellen Sie sicher, dass Sie dies nur mitAnyRef
Argumenten verwenden, nicht nurAny
HINWEIS: Im Fall von
equals
, wie in Java, wird möglicherweise nicht das gleiche Ergebnis zurückgegeben, wenn Sie die Argumente wechseln, z. B.1.equals(BigInt(1))
wird dort zurückgegeben,false
wo die Umkehrung zurückgegeben wirdtrue
. Dies liegt daran, dass jede Implementierung nur bestimmte Typen überprüft. Primitive Zahlen prüfen nicht, ob das zweite ArgumentNumber
noch vomBigInt
Typ ist, sondern nur von anderen primitiven TypenEinzelheiten
Die
AnyRef.equals(Any)
Methode wird von Unterklassen überschrieben. Eine Methode aus der Java-Spezifikation, die auch für Scala verfügbar ist. Wenn es für eine Instanz ohne Box verwendet wird, wird es als Box aufgerufen, um dies aufzurufen (obwohl in Scala versteckt; in Java mitint
-> offensichtlicherInteger
). Die Standardimplementierung vergleicht lediglich Referenzen (wie in Java).Die
Any.==(Any)
Methode vergleicht zwei Objekte und lässt zu, dass jedes Argument null ist (als würde eine statische Methode mit zwei Instanzen aufgerufen). Es vergleicht, wenn beide sindnull
, und ruft dieequals(Any)
Methode für eine Box-Instanz auf.Die
AnyRef.eq(AnyRef)
Methode vergleicht nur Referenzen, dh dort befindet sich die Instanz im Speicher. Für diese Methode gibt es kein implizites Boxen.Beispiele
1 equals 2
wird zurückkehrenfalse
, wenn es umleitetInteger.equals(...)
1 == 2
wird zurückkehrenfalse
, wenn es umleitetInteger.equals(...)
1 eq 2
wird nicht kompiliert, da beide Argumente vom Typ sein müssenAnyRef
new ArrayList() equals new ArrayList()
wird zurückkehrentrue
, wenn es den Inhalt überprüftnew ArrayList() == new ArrayList()
wird zurückkehrentrue
, wenn es umleitetequals(...)
new ArrayList() eq new ArrayList()
wird zurückgegebenfalse
, da beide Argumente unterschiedliche Instanzen sindfoo equals foo
wird zurückkehrentrue
, esfoo
sei denn, istnull
, dann wird ein werfenNullPointerException
foo == foo
wird zurückkehrentrue
, auch wennfoo
istnull
foo eq foo
wird zurückgegebentrue
, da beide Argumente auf dieselbe Referenz verweisenquelle
Es gibt einen interessanten Unterschied zwischen
==
undequals
fürFloat
undDouble
Typen: Sie behandelnNaN
unterschiedlich:Bearbeiten: Wie in einem Kommentar erwähnt - "das passiert auch in Java" - hängt davon ab, was genau das ist:
Dies wird gedruckt
Die
unboxedNan
Ausbeuten werden alsofalse
im Vergleich zur Gleichheit verglichen, da IEEE-Gleitkommazahlen dies so definieren und dies wirklich in jeder Programmiersprache geschehen sollte (obwohl dies irgendwie mit dem Begriff der Identität zu tun hat).Das Boxed NaN ergibt true für den Vergleich mit
==
Java, wenn wir Objektreferenzen vergleichen.Ich habe keine Erklärung für den
equals
Fall, IMHO sollte es sich wirklich genauso verhalten wie==
bei Doppelwerten ohne Box, aber das tut es nicht.In Scala übersetzt ist die Angelegenheit etwas komplizierter, da Scala die primitiven und Objekttypen vereinheitlicht und je
Any
nach Bedarf in das primitive Double und das Boxed Double übersetzt hat. Daher läuft die Scala==
anscheinend auf einen Vergleich primitiverNaN
Werte hinaus,equals
verwendet jedoch diejenige, die für Boxed-Double-Werte definiert ist (es gibt eine Menge impliziter Konvertierungsmagie und es gibt Dinge, die auf Double-Werte gepimpt werdenRichDouble
).Wenn Sie wirklich herausfinden müssen, ob tatsächlich etwas
NaN
verwendet wirdisNaN
:quelle
Suchen Sie in Scala == zuerst nach Nullwerten und rufen Sie dann die Methode equals für das erste Objekt auf
quelle