針對于java.lang.Object已經(jīng)幫我們實(shí)現(xiàn)好了的toString方法,當(dāng)我們自己定義出來的類使用這古老的toString方法的時候,通常不會返回給你一個比較滿意的字符串
那這個字符串由什么組成呢?
首先是有一個類名,加上一個“@”的符號,然后加上這個類的hash code的無符號16進(jìn)制表示
舉個例子,比如上一篇關(guān)于HashCode的文章中的PhoneNumber類
那么它的hash code就是這個樣子: PhoneNumber@163b91
在JavaSE6中對于toString方法的規(guī)范是這樣說的:
“a concise but informative rePResentation that is easy for a person to read”
大意為 簡潔而不失可讀性和信息的表現(xiàn)
對于“PhoneNumber@163b91”這樣的形式來說,十分簡潔,同時也具有一定的可讀性,就是信息的表現(xiàn)略晦澀,難以理解
比起” (707) 867-5309 “ 上面形式的信息的表現(xiàn)力就弱了許多
那么JavaSE6想和我們說其實(shí)就是:
建議所有子類重寫toString方法!
的確是個好的建議
需要注意的是,重寫toString方法的重要性可能不會像我們之前說提過的equals和hashCode方法來的重要,但是,重寫這個方法并且對這個方法做出一個漂亮的實(shí)現(xiàn)會讓我們的類用起來更加的愉快,甚至說,優(yōu)雅!
當(dāng)一個類作為參數(shù)傳遞給println,printf,字符串的連接操作符,或者assert,被debugger打印啊之類的,就會自動地調(diào)用這個類的toString方法
printf是1.5之后才加進(jìn)來的方法,依賴于String.format,這個方法就特別像C語言中的sprintf函數(shù)
如果你實(shí)現(xiàn)好了這個toString方法,那么你在打印一些調(diào)試信息的時候就特別的輕松,如下
System.out.println("Failed to connect: " + phoneNumber);不管你是否重寫了toString方法,程序員們都會試圖像上面這樣來打印調(diào)試信息,只不過,如果你好好的重寫了該方法,那么這條信息就比你不重寫的時候所產(chǎn)生的信息來的有用
重寫一個好的toString方法不僅僅對本類產(chǎn)生作用,它還會延伸到那些擁有該類引用的那些對象的身上!
舉個例子,比如說Collection這樣的集合類,當(dāng)你打印Map的時候你會更加愿意看到“ {Jenny=PhoneNumber@163b91} ”還是“ {Jenny=(707) 867-5309} ”呢?
實(shí)際應(yīng)用中,toString方法需要返回該對象的所有的有意思的信息
正如我們之前提到的phoneNumber類,如果有這么一個集合包含了成千上萬的phoneNumber,那么它應(yīng)該返回一個概括性的描述,這個描述就類似于”Manhattan white pages (1487536 listings)“,這樣的形式,而不是返回那么多條數(shù)據(jù)
理想條件下,我們希望返回的這個string應(yīng)當(dāng)是不言自明的
你還需要做的一個重要的事情就是,當(dāng)你實(shí)現(xiàn)toString方法的時候,是否要在文檔中指定返回值的格式
對于那些值依賴的類來說,比如電話號碼,矩陣之類的,推薦的做法應(yīng)該是在文檔中指定返回值的格式,這樣做的優(yōu)點(diǎn)在于使得一個對象的表述變得標(biāo)準(zhǔn),明確而且具有可讀性,這樣的表達(dá)可以被輸入或者輸出在人類可讀的持久型數(shù)據(jù)對象中,比如說xml文檔
如果你指定了返回值的格式,那么較好的做法是在類中添加靜態(tài)工廠或者構(gòu)造方法,這樣利于程序的拓展之類的,這樣的方法被應(yīng)用在Java 平臺庫中,比如 BigInteger , BigDecimal 以及那些對基本類型的封裝類
指定返回值格式的缺點(diǎn)在于,你的程序的靈活性將降低,也就是說你一旦重新改了這個格式,那么很多以往的程序就無法兼容了,這是我們需要好好考慮的
不管你打不打算指定返回值的格式,你都應(yīng)該在文檔中清楚地說明你的打算,舉個例子:
/*** 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* 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);}有了這些說明,在你的程序的基礎(chǔ)上進(jìn)行開發(fā)的人就不會因?yàn)楦袷叫薷亩?zé)怪你了
需要注意的是,你必須對toString返回的各類信息所在的域提供編程訪問,這對于整個系統(tǒng)的構(gòu)建有著極其重要的意義
新聞熱點(diǎn)
疑難解答
圖片精選