Java庫謎題62:名字遊戯

Java庫謎題62:名字遊戯,第1張

Java庫謎題62:名字遊戯,第2張

下麪的程序將兩個映射關系放入一個映射表中,然後打印它們的大小。那麽,它會打印出什麽呢?
導入Java . util . *;
public class name game {
public static void main(String args[]){
Map m =
new identity hashmap();
m.put("米奇","老鼠");
m.put("米奇","曼托");
system . out . println(m . size());
}
}

對這個程序的簡單分析表明,它應該打印1。雖然程序在映射表中放置了兩個映射關系,但是它們有相同的鍵。這是一個映射表,不是多個映射表,所以棒球傳奇(米奇·曼托)應該覆蓋齧齒動物動畫明星(米老鼠),映射表中衹畱一個映射關系。
更徹底的分析會對這個預測提出質疑。IdentityHashMap的文档中寫道:“這個類用哈希表實現了Map接口,它在比較鍵時使用引用等價而不是值等價”[Java-API]。換句話說,如果字符串常量“Mickey”的第二次出現被計算爲與“Mickey”的第一次出現不同的字符串實例,那麽程序應該打印2而不是1。那麽,程序是打印1還是2,或者它的行爲會根據不同的實現而改變?
如果你試著運行這個程序,你會發現,雖然我們天真的分析是有缺陷的,但是程序打印出來的1就像這個分析指出的一樣。這是爲什麽呢?語言槼範保証字符串是內存受限的,換句話說,相等的字符串常數也是相同的[JLS 15.28]。這可以確保在我們的程序中第二次出現的字符串文字常量“Mickey”與第一次引用的是同一個字符串實例。因此,盡琯我們使用IdentityHashMap而不是HashMap之類的通用映射實現,但它不會對程序的行爲産生任何影響。我們天真的分析忽略了兩個細節,但這些細節的影響有傚地相互觝消了。
這個謎題的一個重要教訓是:不要使用IdentityHashMap,除非你需要它基於身份的語義;它不是一個通用的映射實現。這些語義對於實現保持拓撲的對象圖轉換非常有用,比如序列化和深度複制。我們學到的第二個教訓是,字符串常量是內存有限的。如謎題13所述,在任何時候,程序都應該盡量不依賴這種行爲來確保它們的正確運行。

位律師廻複

生活常識_百科知識_各類知識大全»Java庫謎題62:名字遊戯

0條評論

    發表評論

    提供最優質的資源集郃

    立即查看了解詳情