Kotlinには比較のための2つの演算子があります:
== — 構造的比較(.equals()に相当)。内容をチェックします:a == bはa?.equals(b) ?: (b == null)を呼び出します。=== — 参照比較。両方の変数が同じオブジェクトを指しているかどうかをチェックします:a === bはオブジェクトに対するJavaのa == bに相当します。プリミティブ型に対して(例えばInt):==と===は自動ボクシングのため同じように振る舞う場合がありますが、一般的には==を使用する必要があります。
val a = "Kotlin" val b = "Kotlin" val c = a println(a == b) // true(内容の比較) println(a === b) // false(異なる参照 — 文字列の内部表現はコンパイラに依存します) println(a === c) // true(同じオブジェクト)
Kotlinにおけるa.equals(b)とa == bの違いは何ですか?
多くの人は違いがないと確信していますが、aがnullableの場合、a.equals(b)を呼び出すとNullPointerExceptionが発生し、a == bは安全で、両方がnullの場合はtrue、片方がnullの場合はfalseを返します。
例:
val a: String? = null val b: String? = null println(a == b) // true println(a?.equals(b)) // null(trueではなく、しかしクラッシュはしない) println(a.equals(b)) // NullPointerException
物語
大規模なプロジェクトでnullable文字列をa.equals(b)で活発に比較していたが、a == nullの場合、アプリケーションがクラッシュすることに気づかなかった。バグはかなり稀に再現されたが、本番環境で致命的なクラッシュを引き起こした — a == bに置き換えることで修正された。
物語
オブジェクトを===で比較すると、内容の比較が行われると期待されていたが、===はオブジェクトの同一性をチェックするため、異なるが同じ内容の2つの文字列は===では等しくないことが判明し、データキャッシングのロジックが壊れた。
物語
ボックス化されたInt値(例えばコレクションから)を扱っている際に、開発者はそれらを===で比較し、異なる数字のオブジェクトインスタンスが必ずしもプリミティブとして内部表現されないために予期しない結果を得ていた。これにより、オブジェクトコレクションの操作時に不正な動作を引き起こした。