Saturday, August 7, 2021

10 Tips to override toString() method in Java - ToStringBuilder Netbeans Eclipse

Java toString method
toString method in Java is used to provide clear and concise information about Objects in a human-readable format. A correctly overridden toString method can help in logging and debugging Java programs by providing valuable and meaningful information. Since toString() is defined in java.lang.Object class and its default implementation don't provide much information, it's always a best practice to override the toString method in a subclass. In fact, if you are creating value class or domain class e.g. Order, Trade or Employee,  always override equalshashCode, compareTo, and toString method in Java.

By default toString implementation produces output in the form package.class@hashCode like for our toString() example, Country class’ toString() method will print test.Country@18e2b22 where 18e2b22 is hashCode of an object in hex format, if you call hashCode method it will return 26094370, which is the decimal equivalent of 18e2b22. This information is not very useful while troubleshooting any problem. 

Let’s see a real-life example where you are troubleshooting network connectivity issues, in case of this you want to know which host and port your system is trying to connect and if Socket or ServerSocket class only print default toString information then its impossible to figure out the actual problem, but with a decent toString implementation, they can print useful information like hostname and port

In this Java tutorial, we will see some tips to override the toString method with code examples.


How to override the toString method in Java:

override toString method in Java - Tips and ExampleOverriding toString() method is similar to overriding any method in Java, you need to follow rules of method overriding. Anyway, there are many ways to implement or override toString() method like you can write this method manually, you can use IDE like Netbeans and Eclipse to generate toString method or you can use Apache commons ToStringBuilder to generate toString method in multiple styles like a single line, multi-line, etc. 

Here are few points to remember while overriding toString() method in Java, which will help you to get most from your toString() implementation.



1.Print formatted date e.g. dd-MM-yy instead of raw date

This is very helpful tip while overriding Java’s toString() method. Since toString() of java.util.Date class does not print formatted dates and includes lots of details which is not always necessary. If you are using a particular DateFormat e.g. dd-MM-yy in your application, they you definitely want to see dates on that format instead of the default. IDE normally does not generate formatted Date output and this is something you need to do by yourself  but its worth of effort. See How to print Date in ddMMyy format in Java for more details on formatting Date in Java. You can either use the SimpleDateFormat class or Joda Date time library for this purpose.



2. Document toString format

If your toString() method is not printing data in terms of field=value, Its good idea to document format of toString, especially for value objects like Employee or Student. For example, if toString() method of Employee prints "John-101-Sales-9846387321" than its good idea to specify the format as "name-id-department-contact", but at the same time don't let your client extract information from toString() method and you should always provide corresponding getter methods like getName(), getId(), getContact() etc, because extracting information from toString() representation of Object is fragile and error-prone and client should always a cleaner way to request information.



3. Use StringBuilder to generate toString output

If you writing code for toString() method in Java, then use StringBuilder to append individual attributes.  If you are using IDE like Eclipse, Netbeans, or IntelliJ then also using  StringBuilder and append() method instead of + operator to generate toString method is a good way. By default both Eclipse and Netbeans generate toString method with concatenation operator.



4. Use @Override annotation

Using @Override annotation while the overriding method in Java is one of the best practice in Java. But this tip is not as important as it was in case of overriding equals() and compareTo() method, as overloading instead of overriding can create more subtle bugs there. Anyway, it’s best to use @Override annotation.



5. Print contents of Array instead of the printing array object
An array is an object in Java but it doesn’t override toString method and when you print array, it will use default format which is not very helpful because we want to see contents of Array. By the way, this is another reason why char[] array is preferred over String for storing sensitive data e.g. password. 

Take a moment to see if printing content of array helps your user or not and if it make sense than print contents instead of array object itself. Apart from performance reasons prefer Collection like ArrayList or HashSet over Array for storing other objects.


Bonus Tips

Here are few more bonus tips on overriding toString method in Java

1. Print output of toString in multiple lines or single line based upon it length.
2. Include the full qualified name of the class in toString representation e.g. package.class to avoid any confusion/
3. You can either skip null values or show them, it's better to leave them. Sometimes they are useful as they indicate which fields are null at the time of any incident e.g. NullPointerException.

4. Use key-value format like member.name=member.value as most of IDE also follows that.
5. Include inherited members if you think they provide must-have information in child class.
6. Sometimes an object contains many optional and mandatory parameters like we shown in our Builder pattern example, when it's not practically possible to print all fields in those cases printing meaningful information, not necessary fields is better.



The toString() Example in Java

We will use the following class to demonstrate our toString examples for Netbeans, Eclipse, and Apache's ToStringBuilder utility.

/**
 * Java program to demonstrate How to override toString() method in Java.
 * This Java program shows How can you use IDE like Netbeans or Eclipse
 * and Open source library like Apache commons ToStringBuilder to
 * override toString in Java.
 *
 * @author Javarevisited.blogspot.com
 */


public class Country{
    private String name;
    private String capital;
    private long population;
    private Date independenceDay;

    public Country(String name){
        this.name = name;
    }
 
    public String getName(){ return name; }
    public void setName(String name) {this.name = name;}
 
    public String getCapital() {return capital;}
    public void setCapital(String capital) {this.capital = capital;}

    public Date getIndependenceDay() {return independenceDay;}
    public void setIndependenceDay(Date independenceDay) {this.independenceDay = independenceDay;}

    public long getPopulation() { return population; }
    public void setPopulation(long population) {this.population = population; }

    @Override
    public String toString() {
        return "Country{" + "capital=" + capital + ",
               population="
+ population + ",
               independenceDay="
+ independenceDay + '}';

    }

    public void setIndependenceDay(String date) {
        DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        try {
            this.independenceDay = format.parse(date);
        } catch (ParseException ex) {
            Logger.getLogger(Country.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
   
   public static void main(String args[]){
            Country India = new Country("India");
            India.setCapital("New Delhi");
            India.setIndependenceDay("15/07/1947");
            India.setPopulation(1200000000);
           
            System.out.println(India);      
   }

}




toString method created by Netbeans IDE

toString method generated by Netbeans IDE produce following output for above class :

Country{capital=New Delhi, population=1200000000, independenceDay=Fri Aug 15 00:00:00 VET 1947}

If you look at above output you find that NetBeans does not generated formatted Date for you, instead it calls toString() method of java.util.Date class.



toString() code generated by Eclipse IDE:

By default Eclipse generates following toString method :

@Override
    public String toString() {
        return "Country [name=" + name + ", capital=" + capital
                + ", population=" + population + ", independenceDay="
                + independenceDay + "]";
    }

You can generate code for toString method in Eclipse by clicking Source --Generate toString(). It also provides several options like choosing code style e.g. concatenation operator or StringBuffer etc. Here is the output of toString() method we just created by Eclipse :

Country [name=India, capital=New Delhi, population=1200000000, independenceDay=Tue Jul 15 00:00:00 VET 1947]



Using ToStringBuilder class for overriding Java toString method

Along with many useful classes like PropertyUtils, EqualsBuilder or HashCodeBuilder; Apache commons provides another gem called ToStringBuilder which can generate code for toString() method in different styles. Let’s how does output of toString method looks like in simple style and multi-line style.

Simple Style:
India,New Delhi,1200000000,Fri Aug 15 00:00:00 VET 1947

Multi-line style:
test.Country@f0eed6[
  name=India
  capital=New Delhi
  population=1200000000
  independenceDay=Fri Aug 15 00:00:00 VET 1947
]

NO_FIELD_NAMES_STYLE
test.Country@1d05c81[India,New Delhi,1200000000,Fri Aug 15 00:00:00 VET 1947]

SHORT_PREFIX_STYLE
Country[name=India,capital=New Delhi,population=1200000000,independenceDay=Fri Aug 15 00:00:00 VET 1947]

ToStringStyle.DEFAULT_STYLE
test.Country@1d05c81[name=India,capital=New Delhi,population=1200000000,independenceDay=Fri Aug 15 00:00:00 VET 1947]

Similarly, Google’s open-source library Guava also provides convenient API to generate code for toString method in Java.


When toString method is invoked in Java?

toString is a rather special method and invoked by many Java API methods like println(), printf(), loggers, assert statement, debuggers in IDE, while printing collections and with concatenation operator. 

If subclass doesn't override toString() method than default implementation defined in Object class gets invoked. Many programmers either use logging API like Log4J or java.util.Logger to print logs and often pass Objects there.  logger.info("Customer not found: " + customer) and if Customer doesn't override toString and print meaningful information like customerId, customerName etc than it would be difficult to diagnose the problem. This way its always good to override toString in Java.let's see some benefits of doing this.


Benefits of overriding toString method:

1) As discussed above, correctly overridden toString helps in debugging by printing meaningful information.

2) If value objects are stored in Collection then printing collection will invoke toString on a stored object which can print very useful information. One of the classic examples of not overriding the toString method is Array in Java, which prints default implementation rather than contents of an array. 

Though there are a couple of ways to print contents of an array using Arrays.toString() etc but given Array is an object in Java, would have been much better if Array knows how to print itself much like Collection classes like List or Set.


3) If you are debugging the Java program in Eclipse then using the watch or inspect feature to look at objects, toString will definitely help you.

These are just some of the benefits you get by implementing or overriding the toString method in Java, there are many more which you get and learn by yourself. I hope these tips will help you to get most of your toString implementation. Let us know if you have any unique toString() tips that have helped you in your Java application.

Other Java String articles from Javarevisited Blog

4 comments:

  1. Great tips, One more tip, Which I like to add is using String format method for creating formatted toString representation. It's clear, concise and powerful. Use String.format() to generate your toString() if you are storing key value pairs. Here is an implementation :

    public class Item {
    public final String item;
    public final double price;

    public Item(String name, double price) {
    this.item = name;
    this.price = price;
    }

    @Override
    public String toString() {
    return String.format("%s =\t S$ %.2f", item, price);
    }

    public static void main(String args[]){
    Item nike = new Item("nike", 1002.12);
    System.out.println(nike);

    Item addidas = new Item("addidas", 652.62);
    System.out.println(addidas);

    Item liberty = new Item("liberty", 200.45);
    System.out.println(liberty);
    }
    }

    Result:
    nike = S$ 1002.12
    addidas = S$ 652.62
    liberty = S$ 200.45

    ReplyDelete
  2. Good article ... there is a little problem Independence day should be "15/08/1947" instead of "15/07/1947"

    One doubt, toString() shouldn't print July because you are passing 07 as month. How come it has printed Aug.

    ReplyDelete
  3. Many programmers doesn't realize value of toString() method, its enormous on logging and debugging. If you watch or inspect a variable during Eclipse debugging session, what to you like to see Object@7884393 or something useful e.g. I once wrote a wrapper around Tibrv, to represent Tibco session, initially its toString() was like above, but once I put "network: , daemon: , service: " it become easy for me to find out which sessions are started, stopped or not working.

    ReplyDelete
  4. @hame:
    java.util.Calendar considers January as 0, February as 1, etc. up and until December which is 11.

    Fun times!

    anyway, string + string2 is just as fast now as new StringBuilder(string).append(string2).toString(), so it is now a matter of personal taste.

    ReplyDelete