All 15 equals(), hashCode() & toString() Contracts questions
More in equals(), hashCode() & toString() Contracts
Advertisement
Java › equals(), hashCode() & toString() Contracts

What is the purpose of overriding toString(), and what's the difference between Object's default implementation and a well-designed custom one?

Intermediate

Answer

Object's default toString() returns a largely unhelpful string combining the class name and the object's hash code in hexadecimal (e.g., com.example.Point@7852e922), which is rarely useful for debugging or logging; a well-designed custom toString() returns a concise, human-readable summary of the object's meaningful state (typically the class name plus its key field values), dramatically improving the usefulness of debugger displays, log output, and exception messages that happen to include the object, without needing to manually inspect individual fields.
public class Point {
    private final int x, y;

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

System.out.println(new Point(3, 4));
// Default would print: Point@7852e922 (unhelpful)
// Custom prints: Point{x=3, y=4} (immediately useful for debugging)
Real-world example A debugging session investigating a failed order calculation is significantly sped up because the Order class had a well-implemented toString() automatically printing all relevant order fields whenever an Order instance appeared in a log statement or exception message, versus needing to manually inspect the object through a debugger without it.

Common follow-ups: How do IDEs and tools like Lombok's @ToString help automate generating a reasonable toString() implementation?;What are the risks of including sensitive data (like a password field) in a toString() implementation, especially given logging frameworks might capture it?