Effective Java 2.0_中文版_Item 10

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

Item10: 總是重寫toString方法

盡管java.lang.Object提供了toString方法的實現(xiàn)恨旱,但是通常情況下它返回的字符串不是使用類的用戶想要的深浮。返回的字符串包含類名岳守,后面是一個@符號加上哈希碼的十六進制表示敲霍,例如PhoneNumber@163b91toString的通用約定指出蝇刀,返回值應(yīng)該是“簡潔但易讀的信息表示”[JavaSE6]骏庸。雖然可以認為PhoneNumber@163b91簡潔易讀杂数,但它與(707) 867-5309相比,它的信息不夠豐富锉试。toString約定進一步指出猫十,“建議所有的子類重寫這個方法”。確實是個好建議呆盖。

雖然它不像遵守equalshashCode約定(Item 8, Item 9)那樣重要炫彩,但是提供一個好的toString實現(xiàn)可以使你的類用起來更舒適。當對象傳到println絮短,printf江兢,字符串連接操作符,或assert中丁频,或通過調(diào)試器打印時杉允,會自動調(diào)用toString方法。(Java 1.5版本中平臺加入了printf方法席里,相關(guān)的方法包括String.format叔磷,類似于C語言中的sprintf方法)。

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

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

無論你是否重寫toString方法改基,程序員們都會以這種方式生成診斷信息,但除非你重寫了toString方法咖为,否則這些信息是無用的秕狰。提供一個好的toString方法的好處是除了類的實例之外,也擴展了包含這些實例引用的對象躁染,尤其是集合鸣哀。當打印一個映射時,{Jenny=PhoneNumber@163b91}{Jenny=(707) 867-5309}你更喜歡哪一個吞彤?

當實踐時我衬,toString方法應(yīng)該返回包含在對象中的所有的感興趣信息叹放,正如剛才電話號碼的例子展示的那樣。如果對象很大或它包含不能用字符串表示的狀態(tài)挠羔,重寫toString方法是不切實際的井仰。在這種情況下,toString應(yīng)該返回一個概要信息破加,例如Manhattan white pages (1487536 listings)Thread[main,5,main]俱恶。理想情況下,字符串應(yīng)該是自解釋的拌喉。(Thread例子不能滿足這樣的要求速那。)

當實現(xiàn)toString時,你要做的一個重要決定是是否在文檔中指定返回值的形式尿背。對于值類建議你這樣做端仰,例如電話號碼或矩陣。指定返回值形式的優(yōu)勢在于它能為對象提供一個標準的田藐,清晰的荔烧,可讀的表示。這個表示可以用在輸入輸出中汽久,也可以用在一致的可讀數(shù)據(jù)對象中鹤竭,例如XML文檔。如果你指定了這個形式景醇,提供一個匹配的靜態(tài)工廠或構(gòu)造函數(shù)通常是一個好主意臀稚,程序員可以很容易地在對象和它的字符串表示之間來回轉(zhuǎn)換。Java平臺庫中許多值類都采用了這個方法三痰,包括BigInteger吧寺,BigDecimal和大多數(shù)基本類型的包裝類。

指定toString返回值形式的劣勢在于一旦你指定了它散劫,假設(shè)你的類被廣泛使用稚机,你就必須一直堅持它。程序員將會寫代碼轉(zhuǎn)換這種表示获搏,產(chǎn)生這種形式并將它嵌入到持久化數(shù)據(jù)中赖条。如果你在將來的版本中更改了表示形式,你將會破壞他們的代碼和數(shù)據(jù)常熙,他們將會抱怨纬乍。如果你沒有指定一個形式,你保留了添加信息的靈活性或者在后續(xù)版本改進這種形式症概。

無論你決定是否指定格式蕾额,你都應(yīng)該清楚地表明你的意圖。如果你指定了格式彼城,你應(yīng)該準確的去做。例如,下面的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);
}

如果你沒有指定格式募壕,文檔注釋讀起來應(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() { ... }

寫代碼或持久化數(shù)據(jù)的依賴于格式細節(jié)的程序員调炬,在讀了這個文檔之后,一旦格式改變舱馅,只能自己負責(zé)后果缰泡。

無論你是否指定了格式,都應(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閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件红省,死亡現(xiàn)場離奇詭異额各,居然都是意外死亡,警方通過查閱死者的電腦和手機吧恃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門虾啦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痕寓,你說我怎么就攤上這事傲醉。” “怎么了呻率?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵硬毕,是天一觀的道長。 經(jīng)常有香客問我礼仗,道長吐咳,這世上最難降的妖魔是什么逻悠? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮韭脊,結(jié)果婚禮上童谒,老公的妹妹穿的比我還像新娘。我一直安慰自己沪羔,他們只是感情好饥伊,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蔫饰,像睡著了一般琅豆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篓吁,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天茫因,我揣著相機與錄音,去河邊找鬼越除。 笑死节腐,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的摘盆。 我是一名探鬼主播翼雀,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼孩擂!你這毒婦竟也來了狼渊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤类垦,失蹤者是張志新(化名)和其女友劉穎狈邑,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚤认,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡米苹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了砰琢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蘸嘶。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖陪汽,靈堂內(nèi)的尸體忽然破棺而出训唱,到底是詐尸還是另有隱情,我是刑警寧澤挚冤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布况增,位于F島的核電站,受9級特大地震影響训挡,放射性物質(zhì)發(fā)生泄漏澳骤。R本人自食惡果不足惜歧强,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宴凉。 院中可真熱鬧誊锭,春花似錦表悬、人聲如沸弥锄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽籽暇。三九已至,卻和暖如春饭庞,著一層夾襖步出監(jiān)牢的瞬間戒悠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工舟山, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绸狐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓累盗,卻偏偏與公主長得像寒矿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子若债,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

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