В чём разница между == и === в Kotlin?

В Kotlin == и === — два разных оператора сравнения, и они имеют разное семантическое значение:

🔹 == — сравнение по значению (equivalent to equals())

  • Это перегружаемый оператор: под капотом вызывает equals() (если он определён).

  • Используется для логического сравнения объектов: содержимое, поля и т.п.

  • Даже если два объекта — разные экземпляры, но у них одинаковые значения, == вернёт true.

Пример:

val a = "hello"
val b = "hello"
println(a == b) // true

Хотя a и b могут быть разными объектами в памяти, их значения равны → equals() возвращает true.

🔸 === — сравнение по ссылке (reference equality)

  • Проверяет, один и тот же ли это объект в памяти.

  • Возвращает true только если переменные ссылаются на один и тот же экземпляр.

Пример:

val a = "hello"
val b = "hello"
println(a === b) // true или false  зависит от интернирования строк

Для строк может быть true из-за кэширования, но:

val x = String(charArrayOf('h','e','l','l','o'))
val y = String(charArrayOf('h','e','l','l','o'))
println(x == y) // true  содержимое одинаковое
println(x === y) // false  разные объекты в памяти

🧠 Таблица различий

Оператор Что сравнивает Аналог в Java Тип сравнения
\== Значение (логическое равенство) a.equals(b) Переопределяемый
--- --- --- ---
\=== Ссылку (один ли это объект) a == b (сравнение ссылок) Непереопределяемый
--- --- --- ---

⚠️ Примеры с null

Kotlin обрабатывает null безопасно:

val a: String? = null
val b: String? = null
println(a == b) // true
println(a === b) // true (оба null)

📦 Применимость

  • Используйте ==, если хотите сравнить данные (например, в бизнес-логике).

  • Используйте ===, если важно, один ли это объект в памяти (например, при оптимизациях, работе с синглтонами или кэшами).

✅ Пример различий на практике

data class User(val name: String)
val u1 = User("Alice")
val u2 = User("Alice")
println(u1 == u2) // true  equals() сгенерирован автоматически для data class
println(u1 === u2) // false  это два разных экземпляра

→ Даже если значения одинаковые, объекты разные по ссылке.

Итог

Оператор Поведение Когда использовать
\== Сравнивает значения (equals()) В 99% случаев: сравнение содержимого
--- --- ---
\=== Сравнивает ссылки (один объект?) Когда важно, один ли это экземпляр в памяти
--- --- ---

Понимание разницы между == и === критично при работе с объектами, особенно в Kotlin, где логика сравнения может быть неочевидной из-за лаконичного синтаксиса.