Always override tostring in java class

This is a piece of advice from Joshua Bloch on Effective Java book.

Providing a good toString implementation makes your class much more pleasant to use. When practical, the toString method should return all of the interesting information contained in the object. Whether or not you decide to specify the format, you should clearly document your intentions. Provide programmatic access to all of the information contained in the value returned by toString.

Notes about toString() method

  • toString() should return concise but information representation that is easy for a person to read.
  • We should implement toString() method in every instantiable class we write
  • It is recommended to override toString() method in all subclasses unless a superclass already have a good one.
  • A good implementation of toString() method makes the class pleasant to use and easier to debug
  • The toString() method is automatically invoked when an object is passed to println, printf functions
  • toString method should return all of the interesting information contained in the object
  • For value classes, it is recommended to specify the format of the return value
  • The return value of toString() is specified or not we should document our intension
  • In case of static utility class, writing toString() method does not add value
  • We do not need to write toString() method for most enum types

toString really makes it easier to debug since we can use the object’s string representation. We don’t have to manually build a string that gives the information needed on the object.

The Object class has a default toString() implementation which is not that helpful. See the example below:


    public class User {
        String name;
        int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }

    public class Main {
        public static void main(String[] args) {
            User userObj = new User("Joe", 25);
            System.out.println(userObj);
        }
    }

    // Output 
    $User@7ea2412c

Now if we override the toString() method we could do the following:

    public class User {
        String name;
        int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return String.format("Name: " + name + " and age is: " + age);
        }
    }

    public class Main {
        public static void main(String[] args) {
            User userObj = new User("Joe", 25);
            System.out.println(userObj);
        }
    }
    // Output 
    Name: Joe and age is: 25