В чем разница между == и === в котлине

В чем разница между двумя операторами сравнения == а также === в Котлине?

class A {
  var foo = 1
}

var a1 = A()
var a2 = A()

println(a1 == a2)  // output false
println(a1 === a2) // output false

a1 = a2 

println(a1 == a2)  // output true
println(a1 === a2) // output true

4 ответа

Решение

В Котлине доступны два типа равенства. Это: Структурное равенство и ссылочное равенство.

class A {
  var foo = 1
}

var a1 = A()
var a2 = A()

Вот a1 а также a2 два экземпляра класса A,

println(a1 == a2)

Это печатает false так как a1 а также a2 не являются структурно равными.

println(a1 === a2)

Это печатает false так как a1 а также a2 не ссылаются на один и тот же объект.

Но, если вы выполните эту строку: a1 = a2 затем,

a1 и a2 будут структурно равны, а a1 ссылается на экземпляр a2. Вот почему,

println(a1 == a2)
println(a1 === a2)

обе эти строки возвращают истину.

Короче говоря, из документов:

В Котлине существует два типа равенства:

  • Структурное равенство (проверка на equals()) => ==
  • Ссылочное равенство (две ссылки указывают на один и тот же объект) => ===

Подробный ответ:

Структурное равенство (==)

Отрицательный аналог == является !=

По соглашению такое выражение, как a == b переводится на:

a?.equals(b) ?: (b === null)

если a не является null, он называет equals(Any?) функция, иначе он проверяет, что b ссылочно равно null.

Чтобы обеспечить реализацию пользовательской проверки равенства, переопределите equals(other: Any?): Booleanфункция. Функции с тем же именем и другими сигнатурами, например equals(other: Foo), не влияют на проверку равенства с операторами. == и !=.

Референтное равенство (===)

Отрицательный аналог === является !==

a === b оценивает true если и только если a и bуказать на тот же объект. Для значений, которые во время выполнения представлены как примитивные типы (например, Int), === проверка равенства эквивалентна == чек.

Объяснение кода

Предположим, что определение A как вы определили в своем вопросе.

Фрагмент 1

>>> var a1 = A()
>>> var a2 = A()
>>> a1 == a2 // a1 and a2 are different instances of A
false
>>> a1 == a1
true
>>> a2 == a2
true
>>> a1 === a2 // a1 and a2 have references to different objects
false

Для обычных занятий реализация equals унаследовано от Any, и просто сделайте объект равным самому себе.

Фрагмент 2

>>> var a1 = A()
>>> var a2 = A()
>>> a1 = a2 
>>> a1 == a2
true
>>> a1 === a2
true

a1 и a2 указывают на тот же объект, поэтому a1 == a2 и a1 === a2 верните истину.

Фрагмент 3

Давайте переопределим equals(Any?) из A следующим образом:

class A {
    var foo = 1
    override fun equals(other: Any?): Boolean {
        if (other == null || other !is A)
            return false
        return foo == (other as A).foo
    }
}

Теперь запустим следующее:

>>> var a1 = A()
>>> var a2 = A()
>>> a1 == a2
true
>>> a1 === a2
false

Заметить, что a1 и a2 структурно равны, даже если они ссылаются на разные объекты.

Структурное равенство означает, что контент должен быть одинаковым.

      "checks for equals() or ==".

Ссылочное равенство означает, что оба экземпляра должны указывать на один и тот же указатель.

      "two objects points to same reference or ==="

Вы можете переопределить equals() и сделать то, что показано ниже.

      class Person(val p : String) {

  override fun toString(): String = "Person(p$p)"
    override fun equals(other: Any?): Boolean {
        if(other == null || other !is Person) {
           return false
        }
       return p == other.p
    }
}

давайте проверим это.

      var a = Person("abc")
var b = Person("abc")

Line 1 => println(a == b)
Line 2 => println(a === b)

Line1 печатает "true"

Line2 печатает «ложь»

      a = b

Line1 печатает "true"

Line2 печатает "true"

Окончательно,

=== всегда проверяет равенство ссылок, тогда как == проверяет эквивалентное содержимое и основано на вашей реализации.

Операторы Kotlin == и === (свежий взгляд: 6 случаев)

В Kotlin, если a и b представляют две переменные, тогда println(a==b) проверяет, являются ли два значения структурно равными или нет. Но println(a===b) проверяет, имеют ли a и b одинаковую ссылку или нет. Следующие примеры прояснят это.

      // Case 1 : a and b are both Int
// EqCase1.kt
fun main() {
    var a = 5
    var b = 7
    println(a==b) // false
    //println(a===b) // identity equality for Int is deprecated
    a = b
    println(a==b) // true
    //println(a===b) // identity equality for Int is deprecated
}


// Case 2 : a and b are Double and Integer
// EqCase2.kt
fun main() {
    var a = 5.0
    var b = 7
    //println(a==b) //  operator '==' cannot be applied to 'Double' and 'Int'
    //println(a===b) // operator '===' cannot be applied to 'Double' and 'Int'
    //a = b // inferred type is Int but Double was expected
    //println(a==b) //  inferred type is Int but Double was expected
    println(a===b) // identity equality for Int is deprecated
}


// case 3 : a and b are mathematically same but of different types (Double and Any(say Int))
// EqCase3.kt
fun Eq(a: Double,b: Any) =  if (a == b) "(a == b) is true" else "(a == b) is false"
//fun Eq1(a: Double,b: Any) =  if (a === b) "(a === b) is true" else "(a === b) is false"
fun main() {
    println(Eq(5.0,5)) // (a == b) is false
    //println(Eq1(5.0,5)) 
}

/* O/p
EqCase3.kt:5:34: warning: identity equality for arguments of types Double and Any can be unstable because of implicit boxing
fun Eq1(a: Double,b: Any) =  if (a === b) "(a === b) is true" else "(a === b) is false"
*/


// Case 4 : a and b are both Booleans
// EqCase4.kt
fun main() {
    var a = true
    var b = false
    println(a==b) // false
    //println(a===b) // identity equality for arguments of Boolean is deprecated
    a = b
    println(a==b) // true
    //println(a===b) // identity equality for arguments of Boolean is deprecated
}


// Case 5 : a and b are both Strings
// EqCase5.kt
fun main() {
    var a = "Anil"
    var b = "Vijay"
    println(a==b) // false
    println(a===b) // false
    a = b
    println(a==b) // true
    println(a===b) // true
}


// Case 6 : a and b are both of type arrayOf
// EqCase6.kt
fun main() {
    var a = arrayOf("A","B","C")
    var b = arrayOf("a","b","c")
    println(a==b) // false
    println(a===b) // false
    a = b
    println(a==b) // true
    println(a===b)  // true
}
Другие вопросы по тегам