Scalaの_==
_と.equals()
の違いは何ですか?また、どちらを使用するのですか?
実装はJavaと同じですか?
編集:関連する質問では、AnyVal
の特定のケースについて説明しています。より一般的なケースはAny
です。
通常は==
を使用しますが、equals
sを適切に処理することを除いて、null
にルーティングします。参照の平等(めったに使用されない)はeq
です。
==
はfinalメソッドであり、.equals
を呼び出しますが、これはfinalではありません。
これは、==
がメソッドではなく演算子であり、オブジェクトの参照の等価性を厳密に比較するJavaとは根本的に異なります。
equals
メソッドをオーバーライドして、各インスタンスのコンテンツを比較します。これは、Javaで使用されるequals
メソッドと同じです==
_演算子を使用して、null
参照を気にせずに比較しますeq
メソッドを使用して、両方の引数が[〜#〜] exactly [〜#〜]同じ参照であるかどうかを確認します。これがどのように機能するか理解していない限り使用しないことをお勧めします。多くの場合、代わりにequals
が必要なものに対して機能します。そして、これをAnyRef
だけでなくAny
引数でのみ使用するようにしてください注:equals
の場合、Javaの場合と同様に、引数を切り替えると同じ結果が返されない場合があります。たとえば、1.equals(BigInt(1))
はfalse
を返します。 true
を返します。これは、各実装が特定のタイプのみをチェックするためです。プリミティブ番号は、2番目の引数がNumber
型でもBigInt
型でもないが、他のプリミティブ型のみであるかどうかをチェックしません
AnyRef.equals(Any)
メソッドは、サブクラスによってオーバーライドされます。 Java仕様からのメソッドで、Scalaにも渡されています。ボックス化されていないインスタンスで使用する場合、これを呼び出すためにボックス化されます(Scalaでは隠されていますが、Javaではint
-> Integer
でより明確です)。デフォルトの実装は、参照を比較するだけです(Javaのように)
Any.==(Any)
メソッドは、2つのオブジェクトを比較し、いずれかの引数をnullにすることができます(2つのインスタンスで静的メソッドを呼び出すように)。両方がnull
かどうかを比較し、ボックス化されたインスタンスでequals(Any)
メソッドを呼び出します。
AnyRef.eq(AnyRef)
メソッドはonly参照、つまりインスタンスがメモリ内にある場所を比較します。このメソッドには暗黙的なボクシングはありません。
1 equals 2
_はInteger.equals(...)
にリダイレクトするため、false
を返します1 == 2
_はInteger.equals(...)
にリダイレクトするため、false
を返します1 eq 2
_は、両方の引数がAnyRef
型である必要があるため、コンパイルされませんnew ArrayList() equals new ArrayList()
はコンテンツをチェックするため、true
を返しますnew ArrayList() == new ArrayList()
は、equals(...)
にリダイレクトされるため、true
を返します。new ArrayList() eq new ArrayList()
は、両方の引数が異なるインスタンスであるため、false
を返しますfoo equals foo
_は、true
がfoo
でない限り、null
を返し、NullPointerException
をスローします。foo == foo
_は、true
がfoo
であっても、null
を返しますfoo eq foo
_はtrue
を返します。両方の引数が同じ参照にリンクしているためですequals
およびFloat
タイプの==
とDouble
には興味深い違いがあります:NaN
の扱いが異なります:
scala> Double.NaN == Double.NaN
res3: Boolean = false
scala> Double.NaN equals Double.NaN
res4: Boolean = true
編集:コメントで指摘されたように-「これはJavaでも起こる」-正確に何に依存するかthis :
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));
}
これは印刷されます
false
true
true
したがって、unboxedNan
は、等しいかどうかを比較するとfalse
になります。これは、IEEE浮動小数点数が定義する方法であり、すべてのプログラミング言語で実際に発生するためです(ただし、アイデンティティの概念が混乱します)。
ボックス化されたNaNは、オブジェクト参照を比較しているので、Java)の==
を使用した比較に対してtrueを返します。
equals
の場合の説明はありませんが、私見では、ボックス化されていないdouble値で==
と同じように動作するはずですが、そうではありません。
Scalaに変換すると、問題はScalaがプリミティブ型とオブジェクト型をAny
に統一し、プリミティブdoubleとしたがって、scala ==
は、明らかにNaN
値の比較に要約されますが、equals
はboxed Double値で定義されたものを使用します(多くの暗黙的な変換マジックが進行しており、RichDouble
によってdoubleに変換されたものがあります)。
実際に何かがNaN
であるかどうかを調べる必要がある場合は、isNaN
を使用します。
In Scala ==最初にNull値をチェックしてから、最初のオブジェクトでequalsメソッドを呼び出します