Equality
In Kotlin, there are two types of equality:
Structural equality (
==
) - a check for theequals()
functionReferential equality (
===
) - a check for two references pointing to the same object
Structural equality
Structural equality verifies if two objects have the same content or structure. Structural equality is checked by the ==
operation and its negated counterpart !=
. By convention, an expression like a == b
is translated to:
If a
is not null
, it calls the equals(Any?)
function. Otherwise (a
is null
), it checks that b
is referentially equal to null
:
Note that there's no point in optimizing your code when comparing to null
explicitly: a == null
will be automatically translated to a === null
.
In Kotlin, the equals()
function is inherited by all classes from the Any
class. By default, the equals()
function implements referential equality. However, classes in Kotlin can override the equals()
function to provide a custom equality logic and, in this way, implement structural equality.
Value classes and data classes are two specific Kotlin types that automatically override the equals()
function. That's why they implement structural equality by default.
However, in the case of data classes, if the equals()
function is marked as final
in the parent class, its behavior remains unchanged.
Distinctly, non-data classes (those not declared with the data
modifier) do not override the equals()
function by default. Instead, non-data classes implement referential equality behavior inherited from the Any
class. To implement structural equality, non-data classes require a custom equality logic to override the equals()
function.
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 !=
.
Structural equality has nothing to do with comparison defined by the Comparable<...>
interface, so only a custom equals(Any?)
implementation may affect the behavior of the operator.
Referential equality
Referential equality verifies the memory addresses of two objects to determine if they are the same instance.
Referential equality is checked by the ===
operation and its negated counterpart !==
. a === b
evaluates to true if and only if a
and b
point to the same object:
For values represented by primitive types at runtime (for example, Int
), the ===
equality check is equivalent to the ==
check.
Floating-point numbers equality
When the operands of an equality check are statically known to be Float
or Double
(nullable or not), the check follows the IEEE 754 Standard for Floating-Point Arithmetic.
The behavior is different for operands that are not statically typed as floating-point numbers. In these cases, structural equality is implemented. As a result, checks with operands not statically typed as floating-point numbers differ from the IEEE standard. In this scenario:
NaN
is equal to itselfNaN
is greater than any other element (includingPOSITIVE_INFINITY
)-0.0
is not equal to0.0
For more information, see Floating-point numbers comparison.
Array equality
To compare whether two arrays have the same elements in the same order, use contentEquals()
.
For more information, see Compare arrays.