Hurry! Try our new Interactive Courses for FREE. 🥳   🚀

Java toString() Method

The toString() method is part of the Object class and returns a string representation of an object. This method provides a way of textually representing an object in Java. All the Java classes internally inherit the Object class. So, all the Java classes can override this method.

In this tutorial, we will learn about the toString() function.

Default Implementation

The Object class provides an implementation for the toString() method. However, this implementation doesn't give a lot of information about the object and its field. It just returns a string that contains the class name of the object and the object's hashcode. These two components are separated by @.

public String toString()
{
    return getClass().getName()+"@"+Integer.toHexString(hashCode());
}

Let's create a class and view the output given by this method.

class Student
{
	String name;
	double gpa;
	
	Student(String s, double d)
	{
		this.name = s;
		this.gpa = d;
	}
}
public class Demo
{	
	public static void main(String[] args)
	{
		Student s = new Student("Justin", 8.81);
		String studentDetail = s.toString();
		System.out.print(studentDetail);
	}
}


Student@7a81197d

Note that this method is also implicitly called by the System.out.print() method. The following code demonstrates this.

class Student
{
	String name;
	double gpa;
	
	Student(String s, double d)
	{
		this.name = s;
		this.gpa = d;
	}
}

public class Demo
{	
	public static void main(String[] args)
	{
		Student s = new Student("Justin", 8.81);
		System.out.print(s);// toString() called implicitly
	}
}


Student@7a81197d

Overriding the Default Implementation

As discussed above, all classes extend the Object class, and they can override the toString() method. The default implementation doesn't provide a whole lot of information about the Object fields. Let's override this method in our Student class.

class Student
{
	String name;
	double gpa;
	
	Student(String s, double d)
	{
		this.name = s;
		this.gpa = d;
	}	
    //Returning the object fields by overriding toString()
	@Override
	public String toString()
	{
		return "Student[ Name:" + name + " GPA:" + gpa +" ]";
	}
}
public class Demo
{	
	public static void main(String[] args)
	{
		Student s = new Student("Justin", 8.81);
		String studentDetail = s.toString();
		System.out.print(studentDetail);
	}
}


Student[ Name:Justin GPA:8.81 ]

Overriding the Default Implementation for Complex Objects

If our class contains references to other objects, then we also need to override the toString() method in the referenced object class.

For example, let's add an Address class field to our Student class and view the output of the overridden toString() method.

class Student
{
	String name;
	double gpa;
	Address studentAddress;//referenced object
	
	Student(String s, double d, Address add)
	{
		this.name = s;
		this.gpa = d;
		this.studentAddress = add;
	}
	@Override
	public String toString()
	{
		return "Student[ Name:" + name + " GPA:" + gpa + " Address:" + studentAddress +" ]";
	}
}
class Address
{
	int postalCode;
	Address(int i)
	{
		this.postalCode = i;
	}
}
public class Demo
{	
	public static void main(String[] args)
	{
		Address add = new Address(100012);
		Student s = new Student("Justin", 8.81, add);
		String studentDetail = s.toString();
		System.out.print(studentDetail);
	}
}


Student[ Name:Justin GPA:8.81 Address:Address@24d46ca6 ]

As we can see, the Address class uses the default implementation. We get the Address class name and the object hashcode, but it doesn't include the postal code. We need to override the toString() method in the Address class to rectify this problem.

class Student
{
	String name;
	double gpa;
	Address studentAddress;
	
	Student(String s, double d, Address add)
	{
		this.name = s;
		this.gpa = d;
		this.studentAddress = add;
	}
	
    //toString() method for Student class
	@Override
	public String toString()
	{
		return "Student[ Name:" + name + " GPA:" + gpa 
				+ " Address:" + studentAddress +" ]";
	}
}

class Address
{
	int postalCode;
	Address(int i)
	{
		this.postalCode = i;
	}
	
    //toString() method for Address class
	@Override
	public String toString()
	{
		return "Address[ Postal Code:" + postalCode +" ]";
	}
}

public class Demo
{	
	public static void main(String[] args)
	{
		Address add = new Address(100012);
		String addressStr = add.toString();
		System.out.println(addressStr);
		
		Student s = new Student("Justin", 8.81, add);
		String studentDetail = s.toString();
		System.out.print(studentDetail);
	}
}


Address[ Postal Code:100012 ]
Student[ Name:Justin GPA:8.81 Address:Address[ Postal Code:100012 ] ]

Arrays.toString() Method

The Arrays class also provides a toString() method to display the contents of the array. If our class contains an array data member, we must use Arrays.toString() inside our overridden toString() method. Let's first view the output without the use of Arrays.toString().

class Student
{
	String name;
	double gpa;
	double[] marks;
	
	Student(String s, double d, double[] marks)
	{
		this.name = s;
		this.gpa = d;
		this.marks = marks;
	}
	
    //Overriding toString() method without using Arrays.toString()
	@Override
	public String toString()
	{
		return "Student[ Name:" + name + " GPA:" + gpa + " Marks:" + marks + " ]";
	}
}

public class Demo
{	
	public static void main(String[] args)
	{
		double[] marks = {10.5, 12.21, 19.0};
		Student s = new Student("Justin", 8.81, marks);
		String studentDetail = s.toString();
		System.out.print(studentDetail);
	}
}


Student[ Name:Justin GPA:8.81 Marks:[D@5ca881b5 ]

As we can see, the hashcode of the array is displayed and not the content. Let's use the Arrays.toString() method in our toString() method.

import java.util.Arrays;

class Student
{
	String name;
	double gpa;
	double[] marks;
	
	Student(String s, double d, double[] marks)
	{
		this.name = s;
		this.gpa = d;
		this.marks = marks;
	}
	
    //Using Arrays.toString()
	@Override
	public String toString()
	{
		return "Student[ Name:" + name + " GPA:" + gpa + " Marks:" + Arrays.toString(marks) + " ]";
	}
}

public class Demo
{	
	public static void main(String[] args)
	{
		double[] marks = {10.5, 12.21, 19.0};
		Student s = new Student("Justin", 8.81, marks);
		String studentDetail = s.toString();
		System.out.print(studentDetail);
	}
}


Student[ Name:Justin GPA:8.81 Marks:[10.5, 12.21, 19.0] ]

There is also a deepToString() method that returns an appropriate string representation for multidimensional arrays.

import java.util.Arrays;

public class Demo
{	
	public static void main(String[] args)
	{
		int[][] multiDimArr = {
				{1, 2, 3},
				{4, 5, 6},
				{6, 7, 8},
				{7, 8, 9}
		};
		String multiDimStr = Arrays.deepToString(multiDimArr);
		System.out.print(multiDimStr);
	}
}


[[1, 2, 3], [4, 5, 6], [6, 7, 8], [7, 8, 9]]

Wrappers, Collections, and StringBuffers

A lot of predefined classes have an overridden implementation for the toString() method. It is to make sure that a meaningful string representation of the object of these classes is printed. If we have a data member of these classes, we don't need to use any other method inside our overridden toString() method. The following code demonstrates this.

import java.util.ArrayList;

class Student
{
	StringBuffer name;
	Double gpa;
	ArrayList<Double> marks;
	
	Student(StringBuffer s, double d, ArrayList<Double> marks)
	{
		this.name = s;
		this.gpa = d;
		this.marks = marks;
	}
	
    //No need to use any special method for any fields inside the toString() method
	@Override
	public String toString()
	{
		return "Student[ Name:" + name + " GPA:" + gpa + " Marks:" + marks + " ]";
	}
}

public class Demo
{	
	public static void main(String[] args)
	{
		ArrayList<Double> marks = new ArrayList<>();
		marks.add(10.5); marks.add(12.21); marks.add(19.0);
		Student s = new Student(new StringBuffer("Justin"), 8.81, marks);
		String studentDetail = s.toString();
		System.out.print(studentDetail);
	}
}


Student[ Name:Justin GPA:8.81 Marks:[10.5, 12.21, 19.0] ]

Summary

The Object class provides a toString() method that returns a string representation of Java objects. However, the implementation of this method in the Object class is not very useful. For this reason, a lot of predefined Java classes like Integer, Double, ArrayList, StringBuffer override this method. It is a good practice to override this method in user-defined Java classes as well.