Tips
"Effective Java, third Edition" an English version has been published, the second edition of this book presumably many people have read, known as one of the four major Java books, but the second edition of 2009 published, to now nearly 8 years, but with Java 6, 7, 8, and even 9 of the release, the Java language has undergone profound changes.
In the first time here translated into Chinese version. For everyone to learn to share.
12. Always override the ToString method
Although the object class provides an implementation of the ToString method, the string it returns is not usually what the user of your class wants to see. It consists of a class name followed by an "at" sign (@) and an unsigned hexadecimal representation of the hash code, for example [email protected]
. ToString's general conventions require that the returned string should be "a concise but informative representation that is easy for people to read". Although it can be considered [email protected]
concise and easy to read, but it is 707-867-5309
not very rich compared to, but. The ToString General Convention "recommends that all subclasses override this method." Good advice, indeed!
While it's not as important as complying with the Equals and Hashcode conventions (entries 10 and 11), providing a good ToString implementation makes your classes easier to use and easier to debug for systems that use this class. The ToString method is called automatically when the object is passed to the println, printf, string connection operator, or assertion, or when printed by the debugger. Even if you never call ToString on an object, other people can. For example, a component that has a reference to an object may contain a string representation of the object in the log error message. If you fail to override ToString, the message may be useless.
If PhoneNumber
a good tostring method is provided, then generating a useful diagnostic message is as simple as the following:
System.out.println("Failed to connect to " + phoneNumber);
The programmer will generate diagnostic messages in this manner, regardless of whether you rewrite ToString, but unless you do, these messages will not be useful. The benefits of providing a good ToString method include not only instances of classes, but also objects that contain instance references, especially collections. Which one do you see when you print the Map object, {[email protected]}
or {Jenny=707-867-5309}
?
In fact, the ToString method should return all the information it needs to be concerned about in the object, as shown in the phone number example. This is impractical if the object is large or contains a state that is not conducive to a string representation. In this case, ToString should return a digest, such as a Manhattan residential phone directory (1487536 listings)
thread [main,5,main]
. Ideally, the string should be self-explanatory (the threading example does not follow this). Failure to include interesting information about all objects in a string representation can lead to a particularly annoying penalty: The test failure report looks like this:
Assertion failure: expected {abc, 123}, but was {abc, 123}.
One important decision you must make when implementing the ToString method is to specify the format of the return value in the document. It is recommended that you do this for value classes, such as phone numbers or matrix classes. The advantage of specifying a format is that it can be represented as a standard, explicit, and readable object. This representation can be used for input, output, and persisted readability of data objects, such as CSV files. If you specify a format, it is often a good idea to provide a matching static factory or construction method, so programmers can easily convert objects and string representations back and forth. Many value classes in the Java Platform Class Library Take this approach, including biginteger,bigdecimal and most basic type wrapper classes.
The disadvantage of specifying the format of the ToString return value is that if your class is widely used, it will be used for life once the format is specified. The programmer will write code to parse the expression, build it, and embed it in the persisted data. If you change the format representation in a future release, it will break their code and data, and will complain. However, by choosing not to specify a format, you can retain the flexibility to add information or improve formatting in subsequent versions.
Whether or not you decide to specify a format, you should clearly indicate your intentions in the document. If you specify a format, you should do so. For example, here is a ToString method that uses the class in entry 11 PhoneNumber
:
/** * Returns the string representation of this phone number. * The string consists of twelve characters whose format is * "XXX-YYY-ZZZZ", where XXX is the area code, YYY is the * prefix, and ZZZZ is the line number. Each of the capital * letters represents a single decimal digit. * * If any of the three parts of this phone number is too small * to fill up its field, the field is padded with leading zeros. * For example, if the value of the line number is 123, the last * four characters of the string representation will be "0123". */@Override public String toString() { return String.format("%03d-%03d-%04d", areaCode, prefix, lineNum);}
If you decide not to specify a format, then the documentation comment should look like this:
/** * Returns a brief description of this potion. The exact details * of the representation are unspecified and subject to change, * but the following may be regarded as typical: * * "[Potion #9: type=love, smell=turpentine, look=india ink]" */@Override public String toString() { ... }
After reading this note, programmers who generate code that relies on formatting details or persisted data can only blame themselves when the format changes.
The information contained in the value returned by ToString can be accessed programmatically, regardless of whether the format is specified. For example, PhoneNumber
a class should contain AreaCode, prefix, linenum these three properties. If you do not, you will force the programmer to need this information to parse the string. In addition to reducing performance and programmers doing unnecessary work, this process is prone to error, and if the format is changed, it will break and lead to a fragile system. You can convert a string format to a de facto API, even if the specified format may change because the accessor could not be provided.
It is meaningless to write the ToString method in the Static tool Class (entry 4). You should also not write a ToString method in most enum types (entry 34), because Java provides a great way for you. However, you should define the ToString method in any abstract class, and the subclasses of that class share a common string representation. For example, the ToString method on most collection implementations inherits from the abstract collection class.
Google's Open source Autovalue tool, discussed in entry 10, generates a ToString method for you, just like most IDE tools. These methods are ideal for telling you the contents of each property, but not specifically for the meaning of the class. Therefore, for example, it is inappropriate to PhoneNumber
use the auto-generated tostring method for our class (because the phone number has a standard string representation), but Potion
it is perfectly acceptable for our class. That is, the auto-generated tostring method is much better than the method inherited from object, and it does not tell you the value of the object.
Recall that the ToString implementation of object is overridden in each instantiated class, unless the parent class has already done so. It makes the class more comfortable to use and assist in debugging. The ToString method should return a concise and useful description of the object in an aesthetically pleasing format.
Effective Java Third edition--12. Always override the ToString method