← Назад к вопросам

Что делать если объекты нужно сравнить по ссылке

1.0 Junior🔥 121 комментариев
#Kotlin основы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сравнение объектов по ссылке в Kotlin и Android

Оператор === (Identity Equality)

Для сравнения объектов по ссылке используется оператор === (identity equality). Он проверяет, указывают ли две переменные на один и тот же объект в памяти.

val user1 = User("John")
val user2 = User("John")
val user3 = user1

user1 == user2  // false (разные объекты, но одинаковое содержимое)
user1 === user2 // false (разные объекты в памяти)
user1 === user3 // true (одна и та же ссылка)

Различие между == и ===

== — логическое равенство (вызывает equals()):

  • Сравнивает содержимое объектов
  • Можно переопределить
  • Медленнее (вызов функции)
data class User(val name: String)

val u1 = User("Alice")
val u2 = User("Alice")

u1 == u2  // true (equals сравнит name)

=== — сравнение по ссылке (identity):

  • Проверяет, это один и тот же объект
  • Быстро (просто сравнение адресов)
  • Нельзя переопределить
u1 === u2 // false (разные объекты в памяти)

Когда использовать === ?

1. Сравнение Singleton объектов

if (logger === Logger.INSTANCE) {
    // Это точно тот же объект
}

2. Проверка кэша

class ImageCache {
    private val cache = mutableMapOf<String, Bitmap>()
    
    fun isCached(bitmap: Bitmap): Boolean {
        for ((_, cached) in cache) {
            if (bitmap === cached) return true // Точно та же ссылка
        }
        return false
    }
}

3. Проверка null

if (obj === null) { // Эквивалентно obj == null
    // null
}

4. Состояние UI компонентов

class ViewHolder {
    fun bind(item: Item, selectedItem: Item?) {
        if (item === selectedItem) { // Точно выбранный элемент
            itemView.setBackgroundColor(Color.BLUE)
        }
    }
}

5. Обнаружение циклических ссылок

fun printLinkedList(node: Node?, visited: MutableSet<Node> = mutableSetOf()) {
    if (node === null) return
    if (node in visited) {
        println("Циклическая ссылка обнаружена!")
        return
    }
    visited.add(node)
    println(node.value)
    printLinkedList(node.next, visited)
}

Практический пример в Android

class ListAdapter : RecyclerView.Adapter<ViewHolder>() {
    private var selectedItem: Item? = null
    
    fun onItemClicked(item: Item) {
        // Проверяем по ссылке
        if (item === selectedItem) {
            selectedItem = null // Отмена выбора
        } else {
            selectedItem = item
        }
        notifyDataSetChanged()
    }
    
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = items[position]
        if (item === selectedItem) { // Сравнение по ссылке
            holder.itemView.setBackgroundColor(Color.HIGHLIGHT)
        }
    }
}

Важные моменты

  • Immutable объекты могут быть кэшированы JVM, поэтому === может совпадать неожиданно
  • String интернируются"hello" === "hello" может быть true
  • Boxing примитивов — малые Integer кэшируются (-128 до 127)
val a = 1
val b = 1
val c = 128
val d = 128

(a.toInt() === b.toInt()) // true благодаря кэшу
(c.toInt() === d.toInt()) // false разные объекты

Выводы

Оператор === необходим для проверки, это ли один и тот же объект в памяти. Используй его когда важна идентичность, а не равенство содержимого. Это критично для работы с кэшами, синглтонами и состоянием UI в Android.