Kotlin separates value equality from object identity. == calls equals safely, including null handling. === asks whether two references point to the exact same object.
Practical guidance
- Use == for strings, IDs, data classes and domain values.
- Use === only when identity itself is meaningful, such as sentinels or cache instances.
- Data classes generate structural equals from primary-constructor properties.
- Hash-based collections require equals and hashCode to agree.
Working example
data class User(val id: Long, val name: String)
val first = User(7, "Asha")
val second = User(7, "Asha")
check(first == second) // same value
check(first !== second) // different instances
check(null == null)
Common mistakes
- Using === for String comparison can appear to work because of interning, then fail elsewhere.
- Mutable properties used in hashCode can make objects unreachable inside a HashSet.
- Custom equals implementations must be symmetric and consistent.
Key takeaway
Application decisions almost always need structural equality. Reach for identity comparison only when the design explicitly depends on one particular instance.
