Saturday, September 22, 2012

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 Object in human readable format. Correctly overridden toString method can help in logging and debugging of Java program by providing valuable and meaningful information. Since toString() is defined in java.lang.Object class and its default implementation doesn't provide much information, its always a best practice to override toString method in sub class. In fact if you are creating value class or domain class e.g. Order, Trade or Employee,  always override equals, ,hashCode, compareTo and toString method in Java.  By default toString implementation produce output in the form package.class@hashCode e.g. for our toString() example, Country class’ toString() method will print test.Country@18e2b22 where 18e2b22 is hashCode of object in hex format, if you call hashCode method it will return 26094370, which is 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 than 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 toString method with code examples.

How to override 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. Any way there are many way to implement or override toString() method e.g.  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 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.

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 date 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 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 SimpleDateFormat class or Joda Date time library for this purpose.

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 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.

Use StringBuilder to generate toString output
If you writing code for toString() method in Java, then use StringBuilder to append individual attribute.  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 good way. By default both Eclipse and Netbeans generate toString method with concatenation operator .

Use @Override annotation
Using @Override annotation while 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 using @Override annotation.

Print contents of Array instead of printing array object
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 are 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 reason 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 line or single line based upon it length.
2. Include full qualified name of class in toString representation e.g. package.class to avoid any confusion/
3. You can either skip null values or show them, its better to leave them. Sometime 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 thing they provide must have information in child class.
6. Sometime an object contains many optional and mandatory parameters like we shown in our Builder pattern example, when its not practically possible to print all fields in those cases printing a meaningful information, not necessary fields is better.

 toString Example in Java 
We will use 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 provide 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 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 provide 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 Object 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 why 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 than printing collection will invoke toString on stored object which can print very useful information.One of the classic example of not overriding toString method is Array in Java, which prints default implementation rather than contents of array. Though there are couple of ways to print contents of array using Arrays.toString() etc but given Array is an object in Java, would have been much better if Array know how to print itself much like Collection classes like List or Set.

3) If you are debugging Java program in Eclipse than using watch or inspect feature to look object, toString will definitely help you.

These are just some of the benefits you get by implementing or overriding 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 any unique toString() tips which has helped you in your Java application.

Other Java String articles from Javarevisited Blog

4 comments :

Anonymous said...

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

hame said...

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.

Anonymous said...

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.

Anonymous said...

@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.

Post a Comment