toString() Method in Java

Naveen AnamaneniUpdated · 4 min read

Print an object of your own class and you'll see something like Student@1b6d3586. That's the default toString() inherited from Object: the class name, an @, and the hash code in hex. It's correct but useless for a human. Overriding toString() gives your objects a readable text form, which makes printing, logging and debugging far easier.

Default vs Overridden

Report.java▶ Try it
import java.util.Arrays;
import java.util.List;
 
public class Report {
    static class Student {
        private final String name;
        private final int marks;
 
        Student(String name, int marks) {
            this.name = name;
            this.marks = marks;
        }
 
        @Override
        public String toString() {
            return "Student[name=" + name + ", marks=" + marks + "]";
        }
    }
 
    public static void main(String[] args) {
        Student s = new Student("Advitha", 92);
        System.out.println(s);
        System.out.println("Topper: " + s);
 
        List<Student> list = List.of(s, new Student("Navika", 88));
        System.out.println(list);
 
        int[] scores = {92, 88, 75};
        System.out.println(Arrays.toString(scores));
    }
}
Output
Student[name=Advitha, marks=92]
Topper: Student[name=Advitha, marks=92]
[Student[name=Advitha, marks=92], Student[name=Navika, marks=88]]
[92, 88, 75]

How it works

  1. toString() is overridden to return the fields in a readable form. It must be public, because Object.toString() is public.
  2. System.out.println(s) calls s.toString() for you.
  3. String concatenation ("Topper: " + s) calls it too.
  4. A List's own toString() calls toString() on each element.
  5. Arrays don't override toString(). Printing scores directly would show something like [I@4e25154f; Arrays.toString gives [92, 88, 75].

Without the override, the first line would print something like this (the hex part changes from run to run):

Default toString
Report$Student@1b6d3586

Where Java Calls toString()

SituationExample
PrintingSystem.out.println(obj), printf("%s", obj)
String concatenation"Total: " + obj
String.valueOf(obj)Returns "null" for null, otherwise obj.toString()
Collections and mapslist.toString(), map.toString() call it on each element
Debuggers and logsIDEs show toString() in variable views; loggers print it

Writing a Good toString()

  • Include the fields that identify the object and help debugging.
  • Leave out secrets: passwords, tokens, full card or Aadhaar numbers end up in logs.
  • Keep it fast and free of side effects; debuggers call it often.
  • Don't make other code parse it; it's for humans.

Common Mistakes

Printing an array directly. You get [I@.... Use Arrays.toString, or Arrays.deepToString for 2D arrays.

Writing public String tostring(). The lowercase s creates a new method; @Override would catch it.

Calling obj.toString() on a possibly null reference. It throws NullPointerException; String.valueOf(obj) or concatenation print null instead.

Interview Corner

What does the default toString() return?

getClass().getName() + "@" + Integer.toHexString(hashCode()), for example Student@1b6d3586: the class name and the object's hash code in hexadecimal. It's not meaningful to humans, so classes usually override it.

When is toString() called implicitly?

When an object is printed with print, println or printf("%s"), when it's concatenated with a string, when String.valueOf is called on it, and when collections build their own text form from their elements.

Practice

  1. Easy: Override toString() in a Book class with title, author and price, and print a book.
  2. Harder: Override toString() in a BankAccount so it shows the holder and balance, but masks the account number to its last four digits, like XXXXXX4321.

Quick check: toString()

4 questions
1What does the default toString() print?
2Which line calls toString() automatically?
3How should you print the contents of int[] a?
4What must the overriding method's access be?

Key Takeaways

Was this tutorial helpful?

Lesson 152 of 482