Equality
Kotlinでは、二種類のequalityがあります:
- Structural equality (
==-equals()でチェックされる) - Referential equality (
===- 二つの参照が同じオブジェクトを指しているかどうか)
(訳注:普通は同値性と同一性などと言われるが、原文もidentityといった用語を使っていないので、 一般的な用語にはしない事にした。適当な訳語をあてようかとも思ったが意味が分からないだろうから元の単語のままにしておく)
Structural equality
Structural equalityは==演算でチェックされて、その否定は!=でチェックされる。
規約により、a == bは、以下のように翻訳される:
a?.equals(b) ?: (b === null)
aがnullでなければ、aのequals(Any?)関数を呼び出し、
そうでなければ(aがnullなら)bがnullとreferentially equalかをチェックする。
nullと明示的に比較しても最適化される余地は無い事に注意してください:
a == nullは自動的にa === nullに変換されます。
カスタムな同値判定を提供したければ、
equals(other: Any?): Booleanをオーバーライドしてください。
同じ名前でも違うシグニチャの関数、例えばequals(other: Foo)などを定義しても、
==と!=演算子には影響を与えません。
Structual equalityはComparable<...>インターフェースで定義される比較とは一切関係がありません。
この演算子に影響を与えるのはただequals(Any?)をカスタム実装する事だけです。
Referential equality
Referential equalityは===演算でチェックされて、その否定は!==でチェックされます。
a === bがtrueと評価されるのは、aとbが同じオブジェクトを指している時のみです。
実行時にプリミティブ型で表現される値(例えばIntとか)では、
===によるequality判定は==によるチェックと等価です。
浮動小数点数のイコール
イコールのチェックの対象が静的にFloatかDoubleと知れている場合は(nullableかどうかに関わらず)、
その判定はIEEE 754 Standard for Floating-Point Arithmetic標準に従います。
それ以外の場合はstructual equalityが使われ、幾つかのケースで標準に準拠していません。
NaNは自身と等しく、NaNはPOSITIVE_INFINITYも含めてそのほかのすべての値より大きいとされ、
-0.0は0.0とは等しく有りません。
参考: 浮動小数点数の比較