Java Object Class Methods: equals, hashCode, toString, clone, and finalize Explained

Illustration for Java Object Class Methods: equals, hashCode, toString, clone, and finalize Explained
By Last updated:

The Object class is the root of Java's class hierarchy, and its methods form the foundation for all Java objects. Understanding these methods is critical for writing robust, efficient, and maintainable code.


📌 What is the Object Class?

  • Definition: The Object class in java.lang is the ultimate superclass for every Java class.
  • Why it matters: Provides default implementations for common methods like equality checks, string representation, cloning, and cleanup.
  • When to use: Override these methods when you need custom behavior in collections, debugging, or copying objects.

🔹 equals() Method

✅ Concept:

  • Compares objects for equality.
  • Default: Compares memory references (==).
  • Override to compare object state instead of references.

💻 Example:

class Person {
    String name;
    Person(String name) { this.name = name; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Person)) return false;
        Person p = (Person) obj;
        return name.equals(p.name);
    }
}

🔹 hashCode() Method

✅ Concept:

  • Returns an integer hash code.
  • Used in HashMap, HashSet for quick lookup.
  • Must be consistent with equals().

💻 Example:

@Override
public int hashCode() {
    return name.hashCode();
}

🔹 toString() Method

✅ Concept:

  • Returns a string representation.
  • Default: ClassName@HexHashCode.
  • Override for readable output.

💻 Example:

@Override
public String toString() {
    return "Person{name='" + name + "'}";
}

🔹 clone() Method

✅ Concept:

  • Creates a copy of the object.
  • Requires implementing Cloneable.
  • Default is shallow copy.

💻 Example:

class Person implements Cloneable {
    String name;
    Person(String name) { this.name = name; }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

🔹 finalize() Method

✅ Concept:

  • Called before GC deletes an object.
  • Deprecated in Java 9, removed in Java 18.
  • Avoid; use AutoCloseable instead.

💻 Example:

@Override
protected void finalize() throws Throwable {
    System.out.println("Finalize called");
}

🔹 Real-World Analogy

  • equals(): Checking if two keys open the same lock.
  • hashCode(): Key's unique teeth pattern for quick matching.
  • toString(): Label on the key.
  • clone(): Making a duplicate key.
  • finalize(): Key being thrown away when no longer used.

📊 Comparison Table

Method Default Behavior When to Override
equals() Reference comparison Compare object state
hashCode() Based on memory address Work with hash collections
toString() Class@hashcode Debugging, logging
clone() Shallow copy Create object copies
finalize() Cleanup before GC Avoid, use alternative APIs

🚫 Common Mistakes

  • ❌ Overriding equals() without hashCode().
  • ❌ Using mutable fields in hashCode().
  • ❌ Relying on finalize() for resource cleanup.

📈 Performance and Memory

  • hashCode() heavily impacts HashMap performance.
  • clone() can be expensive for deep copies.
  • Overriding toString() has negligible performance impact.

🔧 Best Practices

  • Override equals() and hashCode() together.
  • Make toString() descriptive and concise.
  • Prefer copy constructors over clone() for complex objects.
  • Avoid finalize(), use try-with-resources.

📌 Java Version Relevance

Java Version Change
Java 1.0 Object class introduced
Java 9 finalize() deprecated
Java 18 finalize() removed

✅ Conclusion & Key Takeaways

  • Object class methods define default behavior for all Java objects.
  • Override equals/hashCode for custom equality, toString for readable output.
  • Use cloning carefully, avoid finalize in modern Java.

❓ FAQ

Q1: Can we override equals() without overriding hashCode()?
A: No, it breaks the general contract in collections.

Q2: Is clone() thread-safe?
A: No, synchronization must be handled manually.

Q3: Can we call finalize() manually?
A: Yes, but it's discouraged and unreliable.

Q4: Are hashCode() values unique?
A: Not guaranteed, collisions are allowed.

Q5: Can equals() be static?
A: No, it compares instances.

Q6: Does overriding toString() affect GC?
A: No, it’s only for string representation.

Q7: Is clone() faster than serialization?
A: Shallow clone is faster; deep clone depends.

Q8: Can finalize() revive an object?
A: Yes, but it's an anti-pattern.

Q9: Are all primitive wrappers overriding equals()?
A: Yes, for value comparison.

Q10: Is hashCode() used in TreeMap?
A: No, TreeMap uses compareTo/comparator.