Effective Java 2.0_中英文對照_Item 10

文章作者:Tyan
博客:noahsnail.com | CSDN | 簡書

Item10: Always override toString

While java.lang.Object provides an implementation of the toString method, the string that it returns is generally not what the user of your class wants to see. It consists of the class name followed by an “at” sign (@) and the unsigned hexadecimal representation of the hash code, for example, “PhoneNumber@163b91.” The general contract for toString says that the returned string should be “a concise but informative representation that is easy for a person to read” [JavaSE6]. While it could be argued that “PhoneNumber@163b91” is concise and easy to read, it isn’t very informative when compared to “(707) 867-5309.” The toString contract goes on to say, “It is recommended that all subclasses override this method.” Good advice, indeed!

盡管java.lang.Object提供了toString方法的實現(xiàn)陨倡,但是通常情況下它返回的字符串不是使用類的用戶想要的症见。返回的字符串包含類名垒探,后面是一個@符號加上哈希碼的十六進制表示,例如PhoneNumber@163b91匙瘪。toString的通用約定指出醉顽,返回值應(yīng)該是“簡潔但易讀的信息表示”[JavaSE6]羊赵。雖然可以認(rèn)為PhoneNumber@163b91簡潔易讀独悴,但它與(707) 867-5309相比,它的信息不夠豐富混驰。toString約定進一步指出攀隔,“建議所有的子類重寫這個方法”。確實是個好建議栖榨。

While it isn’t as important as obeying the equals and hashCode contracts (Item 8, Item 9), providing a good toString implementation makes your class much more pleasant to use. The toString method is automatically invoked when an object is passed to println, printf, the string concatenation operator, or assert, or printed by a debugger. (The printf method was added to the platform in release 1.5, as were related methods including String.format, which is roughly equivalent to C’s sprintf.)

雖然它不像遵守equalshashCode約定(Item 8, Item 9)那樣重要昆汹,但是提供一個好的toString實現(xiàn)可以使你的類用起來更舒適。當(dāng)對象傳到println婴栽,printf满粗,字符串連接操作符,或assert中愚争,或通過調(diào)試器打印時映皆,會自動調(diào)用toString方法挤聘。(Java 1.5版本中平臺加入了printf方法,相關(guān)的方法包括String.format捅彻,類似于C語言中的sprintf方法)组去。

If you’ve provided a good toString method for PhoneNumber, generating a useful diagnostic message is as easy as this:

如果你已經(jīng)為PhoneNumber提供了一個好的toString方法,生成有用的診斷信息是很容易的:

System.out.println("Failed to connect: " + phoneNumber);

Programmers will generate diagnostic messages in this fashion whether or not you override toString, but the messages won’t be useful unless you do. The benefits of providing a good toString method extend beyond instances of the class to objects containing references to these instances, especially collections. Which would you rather see when printing a map, “{Jenny=PhoneNumber@163b91}” or “{Jenny=(707) 867-5309}”?

無論你是否重寫toString方法步淹,程序員們都會以這種方式生成診斷信息从隆,但除非你重寫了toString方法,否則這些信息是無用的贤旷。提供一個好的toString方法的好處是除了類的實例之外广料,也擴展了包含這些實例引用的對象砾脑,尤其是集合幼驶。當(dāng)打印一個映射時,{Jenny=PhoneNumber@163b91}{Jenny=(707) 867-5309}你更喜歡哪一個韧衣?

When practical, the toString method should return all of the interesting information contained in the object, as in the phone number example just shown. It is impractical if the object is large or if it contains state that is not conducive to string representation. Under these circumstances, toString should return a summary such as “Manhattan white pages (1487536 listings)” or “Thread[main,5,main]”. Ideally, the string should be self-explanatory. (The Thread example flunks this test.)

當(dāng)實踐時盅藻,toString方法應(yīng)該返回包含在對象中的所有的感興趣信息,正如剛才電話號碼的例子展示的那樣畅铭。如果對象很大或它包含不能用字符串表示的狀態(tài)氏淑,重寫toString方法是不切實際的。在這種情況下硕噩,toString應(yīng)該返回一個概要信息假残,例如Manhattan white pages (1487536 listings)Thread[main,5,main]。理想情況下炉擅,字符串應(yīng)該是自解釋的辉懒。(Thread例子不能滿足這樣的要求。)

One important decision you’ll have to make when implementing a toString method is whether to specify the format of the return value in the documentation. It is recommended that you do this for value classes, such as phone numbers or matrices. The advantage of specifying the format is that it serves as a standard, unambiguous, human-readable representation of the object. This representation can be used for input and output and in persistent human-readable data objects, such as XML documents. If you specify the format, it’s usually a good idea to provide a matching static factory or constructor so programmers can easily translate back and forth between the object and its string representation. This approach is taken by many value classes in the Java platform libraries, including BigInteger, BigDecimal, and most of the boxed primitive classes.

當(dāng)實現(xiàn)toString時谍失,你要做的一個重要決定是是否在文檔中指定返回值的格式眶俩。對于值類建議你這樣做,例如電話號碼或矩陣快鱼。指定返回值格式的優(yōu)勢在于它能為對象提供一個標(biāo)準(zhǔn)的颠印,清晰的,可讀的表示抹竹。這個表示可以用在輸入輸出中线罕,也可以用在一致的可讀數(shù)據(jù)對象中,例如XML文檔窃判。如果你指定了格式闻坚,提供一個匹配的靜態(tài)工廠或構(gòu)造函數(shù)通常是一個好主意,程序員可以很容易地在對象和它的字符串表示之間來回轉(zhuǎn)換兢孝。Java平臺庫中許多值類都采用了這個方法窿凤,包括BigInteger仅偎,BigDecimal和大多數(shù)基本類型的包裝類。

The disadvantage of specifying the format of the toString return value is that once you’ve specified it, you’re stuck with it for life, assuming your class is widely used. Programmers will write code to parse the representation, to generate it, and to embed it into persistent data. If you change the representation in a future release, you’ll break their code and data, and they will yowl. By failing to specify a format, you preserve the flexibility to add information or improve the format in a subsequent release.

指定toString返回值格式的劣勢在于一旦你指定了它雳殊,假設(shè)你的類被廣泛使用橘沥,你就必須一直堅持它。程序員將會寫代碼轉(zhuǎn)換這種表示夯秃,產(chǎn)生這種格式并將它嵌入到持久化數(shù)據(jù)中座咆。如果你在將來的版本中更改了表示格式,你將會破壞他們的代碼和數(shù)據(jù)仓洼,他們將會抱怨介陶。如果你沒有指定格式,你保留了添加信息的靈活性或者在后續(xù)版本改進這種格式色建。

Whether or not you decide to specify the format, you should clearly document your intentions. If you specify the format, you should do so precisely. For example, here’s a toString method to go with the PhoneNumber class in Item 9:

無論你決定是否指定格式哺呜,你都應(yīng)該清楚地表明你的意圖。如果你指定了格式箕戳,你應(yīng)該準(zhǔn)確的去做某残。例如,下面的Item 9中PhoneNumber類的toString方法:

 /**
    * Returns the string representation of this phone number.
    * The string consists of fourteen 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". *
    * Note that there is a single space separating the closing
    s* parenthesis after the area code from the first digit of the * prefix.
*/
@Override public String toString() {
       return String.format("(%03d) %03d-%04d",areaCode, prefix, lineNumber);
}

If you decide not to specify a format, the documentation comment should read something like this:

如果你沒有指定格式陵吸,文檔注釋讀起來應(yīng)該如下:

/**
* 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 comment, programmers who produce code or persistent data that depends on the details of the format will have no one but themselves to blame when the format is changed.

寫代碼或持久化數(shù)據(jù)的依賴于格式細(xì)節(jié)的程序員玻墅,在讀了這個文檔之后,一旦格式改變壮虫,只能自己負(fù)責(zé)后果澳厢。

Whether or not you specify the format,** provide programmatic access to all of the information contained in the value returned by toString**. For example, the PhoneNumber class should contain accessors for the area code, prefix, and line number. If you fail to do this, you force programmers who need this information to parse the string. Besides reducing performance and making unnecessary work for programmers, this process is error-prone and results in fragile systems that break if you change the format. By failing to provide accessors, you turn the string format into a de facto API, even if you’ve specified that it’s subject to change.

無論你是否指定了格式,都應(yīng)該提供toString返回值中包含的所有信息的程序訪問接口囚似。例如剩拢,PhoneNumber類應(yīng)該包含區(qū)域碼,前綴和行號的訪問器谆构。如果你沒有這樣做裸扶,你會迫使需要這個信息的程序員取轉(zhuǎn)換這個字符串。除了為程序員降低效率和造成不必要的工作之外搬素,這個過程中很容易出錯呵晨,而且會導(dǎo)致系統(tǒng)非常脆弱,如果你更改了格式系統(tǒng)會崩潰熬尺。如果沒有提供訪問器摸屠,即使你指明了字符串格式是可以變化的,這個字符串格式也變成了實際上的API粱哼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末季二,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胯舷,老刑警劉巖刻蚯,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異桑嘶,居然都是意外死亡炊汹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門逃顶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讨便,“玉大人,你說我怎么就攤上這事以政“园” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵盈蛮,是天一觀的道長废菱。 經(jīng)常有香客問我,道長眉反,這世上最難降的妖魔是什么昙啄? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任穆役,我火速辦了婚禮寸五,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘耿币。我一直安慰自己梳杏,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布淹接。 她就那樣靜靜地躺著十性,像睡著了一般。 火紅的嫁衣襯著肌膚如雪塑悼。 梳的紋絲不亂的頭發(fā)上劲适,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音厢蒜,去河邊找鬼霞势。 笑死,一個胖子當(dāng)著我的面吹牛斑鸦,可吹牛的內(nèi)容都是我干的愕贡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼巷屿,長吁一口氣:“原來是場噩夢啊……” “哼固以!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤憨琳,失蹤者是張志新(化名)和其女友劉穎诫钓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篙螟,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡尖坤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了闲擦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慢味。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖墅冷,靈堂內(nèi)的尸體忽然破棺而出纯路,到底是詐尸還是另有隱情,我是刑警寧澤寞忿,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布驰唬,位于F島的核電站,受9級特大地震影響腔彰,放射性物質(zhì)發(fā)生泄漏叫编。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一霹抛、第九天 我趴在偏房一處隱蔽的房頂上張望搓逾。 院中可真熱鬧,春花似錦杯拐、人聲如沸霞篡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朗兵。三九已至,卻和暖如春顶滩,著一層夾襖步出監(jiān)牢的瞬間余掖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工礁鲁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盐欺,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓救氯,卻偏偏與公主長得像找田,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子着憨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容