package.class@hashCode
i.e. toString, that was defined in java.lang.Object gives the hash code of the object in hexadecimal form. This is often not very clear and useful.
So when creating a new class, it is customary to override toString() so that the return string contains the class name, names and values of all variables. Overriding the toString method correctly can help with logging and debugging a Java program, it provides valuable and important information.
Simply put, the toString() method is used in Java to get a string object representing the value of a numeric object. In other words, it converts a number to a string. If the method takes a simple data type as an argument, then a string object is returned that represents the value of the simple data type.
Example of Java toString() method
Usually if you create a class, in addition to the toString() method in Java you need to override the equals, hashCode and compareTo methods in order to know how to work with its objects. But for now, let's focus on toString. In most cases, submitting textual information about an object is quite simple. You just need to understand what exactly the user would like to see when logging. Let's give an example and create a Class that describes a point on the plane. It has two coordinates: coordinateX, coordinateY. Naturally, they should be displayed on the screen if a user asks “what object’s this” just like the name of the class itself. This is what we’re going to demonstrate in the overridden toString() method. Now we create the class itself, its fields (coordinates), a constructor, getters for obtaining coordinates (sure, it’s possible not to create them, but from the standpoint of the correct use of OOP, getters are good practice). Just to illustrate, let's also create a method that creates a new point — the sum of the other two, and also override equals and hashCode methods.
public class Point implements Comparable<Point> {
private final int coordinateX;
private final int coordinateY;
public Point(final int coordinateX, final int coordinateY) {
this.coordinateX = coordinateX;
this.coordinateY = coordinateY;
}
public int getX() {
return coordinateX;
}
public int getY() {
return coordinateY;
}
public Point sum(final Point that) {
return new Point(coordinateX + that.coordinateX, coordinateY + that.coordinateY);
}
// here we override toString with coordinates and class name
@Override
public String toString() {
return "Point{"
+ "X: " + getX()
+ ", Y: " + getY()
+ '}';
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null || o.getClass() != this.getClass()) {
return false;
}
@Override
public int hashCode() {
return coordinateX + coordinateY;
}
Now let’s create a testing class and a main method. There we’ve got two points and the third one, that we’re getting from the summation of two points. We apply toString method to this point and print it out.
//toString() method demo
public class Test {
public static void main(String[] args) {
Point myPoint1 = new Point(5,7);
Point myPoint2 = new Point(-2, 8);
Point mySum = myPoint1.sum(myPoint2);
//call toString explicitly
System.out.println(mySum.toString());
}
}
The result of this program work is below:
//toString method demo
public class Test {
public static void main(String[] args) {
Point myPoint1 = new Point(5,7);
Point myPoint2 = new Point(-2, 8);
Point mySum = myPoint1.sum(myPoint2);
//call toString implicitly
System.out.println(mySum);
}
}
What Happens When You Don’t Override toString()?
Every Java class inherits the toString()
method from the Object
class. But if you don’t override it, you’re in for a surprise when printing an object.
Here’s an example:
class Car { }
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
System.out.println(myCar.toString());
}
}
What do you think this prints? Something meaningful? Nope! It prints something like:
Car@5a07e868
That’s the default behavior of toString()
: it returns the class name followed by the object's memory address in hexadecimal form. Not exactly helpful, right? That’s why overriding toString()
is such a good idea!
Overriding toString() to Make It Useful
To make toString()
return meaningful output, we override it. Here’s how:
class Car {
String brand;
int year;
Car(String brand, int year) {
this.brand = brand;
this.year = year;
}
@Override
public String toString() {
return "Car{" + "brand='" + brand + "', year=" + year + "}";
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car("Tesla", 2023);
System.out.println(myCar);
}
}
Now, instead of printing an unreadable object reference, you’ll get:
Car{brand='Tesla', year=2023}
Much better! Now you can instantly see what the object represents.
Using toString() with Arrays – A Common Pitfall
What happens when you call toString()
on an array? Let’s find out:
int[] numbers = {1, 2, 3};
System.out.println(numbers.toString());
Oops! Instead of [1, 2, 3]
, you get something like:
[I@4c203ea1
That’s because toString()
isn’t overridden in arrays. If you want to print an array properly, use Arrays.toString()
instead:
import java.util.Arrays;
int[] numbers = {1, 2, 3};
System.out.println(Arrays.toString(numbers));
Output:
[1, 2, 3]
Using toString() on Different Data Types
While toString()
is commonly used in objects, you can also use it on wrapper classes:
Integer num = 42;
System.out.println(num.toString());
This will print 42
, since Java’s wrapper classes already override toString()
to return their actual value.
GO TO FULL VERSION