toString and the Object Class

OOP · lesson 4 of 43 · 2 min read

What every object inherits from Object, and how to write a toString that is worth reading in a log.

Open this lesson in the learning hub

Key points

  • Every class extends Object, so every object already has toString, equals and hashCode.
  • The inherited toString prints a class name and a hex hash. Useless in a log file. Override it.
  • Include the fields that identify the object. Never include passwords, tokens or card numbers, because logs leak.
  • String concatenation, println and collection printing all call toString for you automatically.
  • A record generates a clear toString for free, along with equals and hashCode.

Example

import java.util.List;

public class Main {
    static class Silent {
        final int x = 1, y = 2;
    }

    static class Point {
        final int x, y;
        Point(int x, int y) { this.x = x; this.y = y; }

        @Override public String toString() {
            return "Point[x=" + x + ", y=" + y + "]";
        }
    }

    record Pixel(int x, int y) { }   // records generate toString for you

    public static void main(String[] args) {
        System.out.println(new Silent());          // Main$Silent@<hex hash> - useless
        System.out.println(new Point(1, 2));       // Point[x=1, y=2]
        System.out.println(new Pixel(3, 4));       // Pixel[x=3, y=4]

        // Collections and string concatenation call toString for you.
        System.out.println(List.of(new Point(1, 2), new Point(5, 6)));
    }
}

Write toString for the person reading the log at 3am. That person is usually you.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the OOP course, and every lesson in it is listed on the OOP contents page.