Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is difference between == and === in kotlin

What is the difference between the comparison operators == and === in Kotlin?

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
like image 887
SergeyBukarev Avatar asked Jul 14 '18 14:07

SergeyBukarev


2 Answers

In Kotlin, two types of equality are available. These are: Structural Equality & Referential Equality.

class A {
  var foo = 1
}

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

Here a1 and a2 are two instances of class A.

println(a1 == a2)

It prints false because a1 and a2 are not structurally equal.

println(a1 === a2)

It prints false because a1 and a2 are not referencing the same object.

But, if you execute this line: a1 = a2 then,

a1 and a2 will be structurally equal and a1 is referencing to the a2 instance. That's why,

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

both these lines returns true.

like image 66
Avijit Karmakar Avatar answered Oct 08 '22 08:10

Avijit Karmakar


Briefly speaking, from the docs:

In Kotlin there are two types of equality:

  • Structural equality (a check for equals()) => ==
  • Referential equality (two references point to the same object) => ===

Detailed answer:

Structural Equality (==)

The negated counterpart of == is !=

By convention, an expression like a == b is translated to:

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

if a is not null, it calls the equals(Any?) function, otherwise it checks that b is referentially equal to null.

To provide a custom equals check implementation, override the equals(other: Any?): Boolean function. Functions with the same name and other signatures, like equals(other: Foo) , don't affect equality checks with the operators == and !=.

Referential Equality (===)

The negated counterpart of === is !==

a === b evaluates to true if and only if a and b point to the same object. For values which are represented as primitive types at runtime (for example, Int ), the === equality check is equivalent to the == check.

Code explanation

Let's assume the definition of A is as you have defined in your question.

Snippet 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

For regular classes, the implementation of equals is inherited from Any, and just make the object equal to itself.

Snippet 2

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

a1 and a2 point to the same object that is why a1 == a2 and a1 === a2 return true.

Snippet 3

Let's override equals(Any?) of A as follows:

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
    }
}

Now let's run the following:

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

Notice that a1 and a2 are structurally equal even though they reference difference objects.

like image 31
lmiguelvargasf Avatar answered Oct 08 '22 08:10

lmiguelvargasf