post-images/overriding-tostring/cover.jpg

Overriding toString()

Hello 😇 Welcome 🤗 In this article, we will discuss Always override toString, the third item of Methods Common to All Objects, the second unit of the Effective Java book.

In this article, I will examine how to override the toString() method in the Object class, what it does, and if there are rules to be followed while writing.

Let's visit our Object class without breaking the tradition, let's see what's in this toString(). As you can see below, if the toString() method is not overridden, the output we will see will be className + @ + hexadecimalHashCode.

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

Many of my colleagues have used the toString() method when developing. I'm sure you've used it before. In the case you use it, you have witnessed two different representations. One of them is the readable state, which gives you meaningful information from the object in which it is called, and the other is something like Object@5cad8086. This complex image is an indication that the class whose toString() method is called is not its own implementation of toString(), but is derived from the Object class.

As a matter of fact, you only have to comply with one contract clause when overriding toString(). This article also states "It should be short, easy to read and informative for the reader" followed by "It is recommended that all subclasses override this method". The text PhoneNumber@5cad8086, which appears when we do not do any override, actually complies with the contract clause. It looks short, easy to read, and gives information. But the information given here is not very meaningful to us. At this point, you understand why we override toString().

public class PhoneNumber {
    private int areaCode;
    private int prefix;
    private int lineNumber;

    public PhoneNumber(int areaCode, int prefix, int lineNumber) {
        this.areaCode = areaCode;
        this.prefix = prefix;
        this.lineNumber = lineNumber;
    }
}

Let me have a class called PhoneNumber which represents my phone number (Of course not real, don't call 🙃). If toString() is not overridden in this class, the image I will encounter is as follows:

System.out.println(new PhoneNumber(707, 867, 5309).toString());
# PhoneNumber@adbbd

As you can see the output of PhoneNumber@adbbd conforms to the contract but doesn't make any sense to me. If I edit my toString() method to produce the more meaningful output:

@Override  
public String toString()  
{  
    return "PhoneNumber{" +  
            "areaCode=" + areaCode +  
            ", prefix=" + prefix +  
            ", lineNumber=" + lineNumber +  
            '}';  
}

My new result will be as follows:

System.out.println(new PhoneNumber(707, 867, 5309).toString());

# PhoneNumber{areaCode=707, prefix=867, lineNumber=5309}

PhoneNumber{areaCode=707, prefix=867, lineNumber=5309} or PhoneNumber@adbbd Which is more understandable and informative? You decide, I won't.

Is it mandatory to override the toString() method? If the question comes to mind, it is not mandatory. If the object you wrote is logged while your application is running, or if an error has occurred due to this object you created, you will see messages like PhoneNumber@adbbd in the logs, since each object derives from the Object class. When detecting a problem or examining what is going on in the application, knowing what is in this value will give you a great advantage.

Do all fields need to be present when overriding the toString() method? This is also mentioned in the contract. You have no such obligation, and it is recommended that you only host important areas as much as possible.

Let me tell you before closing, many IDEs (IntelliJ IDEA ❤️) have plugins to automatically override the toString() method of the object, and through these plugins, you can add the field you want in toString().

auf Wiedersehen ✌🏼

JavaEffective JavaMethods Common to All ObjectstoStrıng()OverridingSoftware ContractIntelliJ IDEA