How do I override the toString(), equals(), and hashCode() methods in Kotlin?

In Kotlin, you usually don’t manually override toString(), equals(), and hashCode() if your class is just a value/data holder. Use a data class instead.

data class User(
    val id: Int,
    val name: String
)

Kotlin automatically generates:

toString()
equals()
hashCode()
copy()
componentN()

Example:

val a = User(1, "Alice")
val b = User(1, "Alice")

println(a)        // User(id=1, name=Alice)
println(a == b)   // true
println(a.hashCode() == b.hashCode()) // true

Manual override

If you need custom behavior, override them explicitly:

class User(
    val id: Int,
    val name: String
) {
    override fun toString(): String {
        return "User(id=$id, name=$name)"
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is User) return false

        return id == other.id && name == other.name
    }

    override fun hashCode(): Int {
        var result = id
        result = 31 * result + name.hashCode()
        return result
    }
}

Important notes

Use == for equality in Kotlin:

a == b

This calls equals() internally.

Use === for reference equality:

a === b

This checks whether both variables point to the exact same object.

Custom equality example

Sometimes you only want equality based on one property, such as id:

class User(
    val id: Int,
    val name: String
) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is User) return false

        return id == other.id
    }

    override fun hashCode(): Int {
        return id
    }

    override fun toString(): String {
        return "User(id=$id, name=$name)"
    }
}

The key rule is: if you override equals(), you should also override hashCode() consistently. Objects that are equal must have the same hash code.