What is difference between == and === in kotlin
Structural Equality means content should be same
"checks for equals() or ==".
Referential Equality means both instances should be pointed to same pointer.
"two objects points to same reference or ==="
You can override equals() and do the stuff as below.
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
}
}
lets test this.
var a = Person("abc")
var b = Person("abc")
Line 1 => println(a == b)
Line 2 => println(a === b)
Line1 prints "true"
Line2 prints "false"
a = b
Line1 prints "true"
Line2 prints "true"
Finally,
=== always checks for reference equality while == checks for equivalent content and is based on your implementation.
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.
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.