Object ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-09-28

Object. Practical Tasks

The Object class is the root of the Java class hierarchy, so every object has its equals(), hashCode(), and toString() methods. By default, equals() compares references, hashCode() ignores the fields, and toString() returns something like Book@1b6d3586. That is why value classes (a point, a book, a money amount) almost always override all three methods together.

This page has 3 hands-on exercises.

What to review before you start

The exercises build on three lessons: the Object class and its methods, the equals() method and its contract, and the toString() method. A quick cheat sheet:

Method What Object's implementation does When to override
equals(Object o) Compares references, just like == When objects with the same data must count as equal
hashCode() Returns a number unrelated to the fields Always together with equals(): equal objects must have equal hash codes
toString() getClass().getName() + "@" + Integer.toHexString(hashCode()) Almost always: for logs, debugging, and console output

Exercise 1. Default Object methods

  1. Create a Book class with the fields title (String), author (String), and year (int), plus a constructor for all three. Do not override any Object methods.
  2. Create two objects with identical data: new Book("War and Peace", "Tolstoy", 1869).
  3. For each object, print the object itself with System.out.println(book), then book.hashCode() and book.getClass().getName().
  4. Print the results of book1 == book2 and book1.equals(book2). Then create a reference Book book3 = book1; and compare book1 with book3 both ways.
  5. In a code comment, explain every line of output: what the Book@... string is made of, why equals() returned false for identical books but true for book3.

Hint: the hexadecimal number after @ in the println output matches Integer.toHexString(book.hashCode()). Verify it in code.

Exercise 2. Overriding toString() and inheritance

  1. Override toString() in Book so it returns a string like Book{title='War and Peace', author='Tolstoy', year=1869}. Add the @Override annotation.
  2. Create a class EBook extends Book with an extra field fileSizeMb (double). Override toString() using super.toString() so you don't repeat the parent's fields.
  3. Check three places where toString() is called implicitly: System.out.println(book), the concatenation "Book: " + book, and printing a List<Book> with println.
  4. Create a Book[] array of three books. Print it with System.out.println(array) and with Arrays.toString(array). Explain why the results differ.
  5. Set a Book variable to null and compare the behavior of System.out.println(book) and book.toString(). Then print String.valueOf(book) and Objects.toString(book, "book not found").

Exercise 3. equals() vs ==: the Point class

  1. Create a Point class with x and y fields (int) and override equals(): two points are equal when both coordinates match. Check in this order: same reference, null, object class, cast, field comparison.
  2. Write a main method that checks every rule of the equals() contract and prints the result of each check:
    a) reflexivity: p.equals(p);
    b) symmetry: p1.equals(p2) and p2.equals(p1);
    c) transitivity for three equal points;
    d) comparing with null returns false without an exception;
    e) comparing with an object of another class, such as the string "1,2", returns false.
  3. Add a String label field to Point that may be null, and include it in the comparison with Objects.equals(label, other.label). Test the cases where label is null in one point and in both.
  4. Compare two strings, String a = "java"; and String b = new String("java");, with == and with equals(). Then compare two int[] arrays with the same contents using equals() and Arrays.equals(). Explain the results.

Hint: a method with the signature equals(Point other) is an overload, not an override: HashSet and List.contains() will never call it. The @Override annotation turns that mistake into a compilation error right away.

Common mistakes

  • Overriding equals() but forgetting hashCode(). Objects can no longer be found in a HashSet or HashMap, even though everything works in an ArrayList. Always override the two methods as a pair.
  • Declaring equals(Point other) instead of equals(Object o). That's an overload: collections call the version from Object and compare references. The @Override annotation protects you.
  • Using different fields in equals() and hashCode(). If hashCode() uses a field that equals() ignores, equal objects end up with different hash codes. Hash the same fields you compare (or a subset of them).
  • Comparing strings and other object fields with == inside equals(). Reference-type fields need equals(), and Objects.equals() if the field can be null.
  • Calling obj.toString() explicitly when obj may be null. You get a NullPointerException; println(obj), string concatenation, and String.valueOf(obj) safely print null.

Before you submit a solution, check it against common Java code style conventions: meaningful names, one class per file, and no unused code.

Frequently Asked Questions

Do I need to override equals() and hashCode() in every class?

No. Override them in value classes that are compared by their data and stored in a HashSet or used as HashMap keys: a point, a money amount, a book's ISBN. Services, controllers, threads, and other objects with an “identity” are fine with the reference comparison inherited from Object. toString(), on the other hand, is worth overriding almost everywhere, for the sake of your logs.

Can hashCode() return a constant, like 42?

Technically yes: the contract isn't broken, because equal objects still get equal hash codes. But every object lands in the same bucket, so a HashMap degrades into a slow linear search: the more elements it holds, the slower each lookup gets. Use Objects.hash() over the same fields you compare in equals().

Should toString() include every field?

No. Leave out passwords, tokens, and personal data: toString() output often ends up in logs. Bidirectional links are dangerous too: if Order prints its Customer and the customer prints its list of Order objects, the calls loop until a StackOverflowError. For such fields, print only the ID.

Comments

Please log in or register to have a possibility to add comment.