Fatskills
Practice. Master. Repeat.
Study Guide: Java OOP-Inheritance Object Class toString equals hashCode
Source: https://www.fatskills.com/surgery/chapter/java-oop-inheritance-object-class-tostring-equals-hashcode

Java OOP-Inheritance Object Class toString equals hashCode

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~5 min read

What This Is and Why It Matters

The Object class in Java is the root of the class hierarchy. Every class in Java is directly or indirectly derived from the Object class. This class provides fundamental methods like toString(), equals(), and hashCode(). These methods are crucial for object representation, comparison, and hashing, which are essential for collections and data structures. Understanding these methods is vital for writing robust, maintainable code. Misusing them can lead to bugs, such as incorrect object comparisons or inefficient collection operations. For instance, failing to override equals() and hashCode() correctly can cause issues in HashMap or HashSet, leading to data loss or incorrect retrieval.

Core Knowledge (What You Must Internalize)

  • Object class: The superclass of all classes in Java. (Why this matters: It provides default implementations for essential methods.)
  • toString(): Converts an object to a string representation. (Why this matters: Useful for logging and debugging.)
  • equals(): Compares two objects for logical equality. (Why this matters: Essential for accurate object comparisons.)
  • hashCode(): Returns an integer hash code for the object. (Why this matters: Critical for efficient storage and retrieval in hash-based collections.)
  • Contract between equals() and hashCode(): If two objects are equal according to equals(), they must have the same hashCode(). (Why this matters: Violating this contract can break hash-based collections.)

Step‑by‑Step Deep Dive

  1. Understand toString():
  2. Action: Override toString() in your class.
  3. Principle: Provide a meaningful string representation of the object.
  4. Example:
    ```java
    public class Person {
    private String name;
    private int age;


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

    } ```
    - ⚠️ Pitfall: Not overriding toString() can result in default, less useful output.

  5. Override equals():

  6. Action: Implement equals() to compare objects logically.
  7. Principle: Check for logical equality, not reference equality.
  8. Example:
    java
    @Override
    public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Person person = (Person) obj;
    return age == person.age && Objects.equals(name, person.name);
    }
  9. ⚠️ Pitfall: Using == for object comparison checks reference equality, not logical equality.

  10. Implement hashCode():

  11. Action: Override hashCode() to return a consistent hash code.
  12. Principle: Use fields involved in equals() to generate the hash code.
  13. Example:
    java
    @Override
    public int hashCode() {
    return Objects.hash(name, age);
    }
  14. ⚠️ Pitfall: Inconsistent hashCode() implementation can cause issues in hash-based collections.

  15. Maintain the contract:

  16. Action: Ensure equals() and hashCode() are consistent.
  17. Principle: If equals() returns true, hashCode() must return the same value.
  18. Example:
    java
    Person p1 = new Person("Alice", 30);
    Person p2 = new Person("Alice", 30);
    System.out.println(p1.equals(p2)); // true
    System.out.println(p1.hashCode() == p2.hashCode()); // true
  19. ⚠️ Pitfall: Violating this contract can lead to unpredictable behavior in collections.

How Experts Think About This Topic

Experts view toString(), equals(), and hashCode() as foundational methods that must be carefully overridden to maintain the integrity of object-oriented design. They think of equals() and hashCode() as a contract that must be honored to ensure reliable behavior in collections and data structures.

Common Mistakes (Even Smart People Make)

  1. The mistake: Not overriding toString().
  2. Why it's wrong: Default implementation provides less useful information.
  3. How to avoid: Always override toString() for meaningful output.
  4. Exam trap: Questions may ask for the output of toString() without overriding.

  5. The mistake: Using == for object comparison.

  6. Why it's wrong: Checks reference equality, not logical equality.
  7. How to avoid: Use equals() for logical comparison.
  8. Exam trap: Questions may trick you with reference vs. logical equality.

  9. The mistake: Inconsistent hashCode() implementation.

  10. Why it's wrong: Can cause issues in hash-based collections.
  11. How to avoid: Use the same fields in hashCode() as in equals().
  12. Exam trap: Questions may test your understanding of the equals() and hashCode() contract.

  13. The mistake: Not overriding hashCode() when overriding equals().

  14. Why it's wrong: Violates the contract between equals() and hashCode().
  15. How to avoid: Always override both methods together.
  16. Exam trap: Questions may ask about the behavior of collections when this contract is violated.

Practice with Real Scenarios

  1. Scenario: You have a class Book with fields title and author.
  2. Question: Override toString(), equals(), and hashCode().
  3. Solution:
    ```java
    public class Book {
    private String title;
    private String author;


     @Override
     public String toString() {
    return "Book{title='" + title + "', author='" + author + "'}"; } @Override public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Book book = (Book) obj;
    return Objects.equals(title, book.title) && Objects.equals(author, book.author); } @Override public int hashCode() {
    return Objects.hash(title, author); }

    } ```
    - Answer: The class Book with overridden methods.
    - Why it works: Provides meaningful string representation and maintains the equals() and hashCode() contract.

  4. Scenario: You have a HashMap storing Book objects.

  5. Question: What happens if you don't override hashCode()?
  6. Solution:
    • The HashMap will use the default hashCode() implementation, which is based on the object's memory address.
    • This can lead to incorrect behavior, such as not finding an object that is logically equal.
  7. Answer: Incorrect behavior in HashMap.
  8. Why it works: Understanding the importance of overriding hashCode() for correct behavior in hash-based collections.

Quick Reference Card

  • Core rule: Override toString(), equals(), and hashCode() for meaningful object representation and comparison.
  • Key formula: hashCode() should use the same fields as equals().
  • Critical facts:
  • toString() provides a string representation.
  • equals() checks for logical equality.
  • hashCode() returns a consistent hash code.
  • Dangerous pitfall: Violating the equals() and hashCode() contract.
  • Mnemonic: "TEH" (ToString, Equals, HashCode) for remembering the methods to override.

If You're Stuck (Exam or Real Life)

  • Check: The implementation of toString(), equals(), and hashCode().
  • Reason: From first principles, think about what each method should do.
  • Estimate: The impact of not overriding these methods.
  • Find the answer: Refer to the Java documentation or reliable online resources.

Related Topics

  • Collections Framework: Understanding how equals() and hashCode() affect collections.
  • Immutability: How immutable objects can simplify equals() and hashCode() implementations.


ADVERTISEMENT