2011-03-13 82 views
0

我有使用HashMap和泛型的Java代碼如下一段:爲什麼Java的HashMap具有不同對象的不同行爲?

import java.util.*; 
import java.io.*; 

public class Map{ 
    static HashMap<Integer, Integer> imap; 
    static HashMap<Integer, Thing> tmap; 

    public static void main(String[] args){ 

     imap = new HashMap<Integer, Integer>(); 
     imap.put(0,0); 
     Integer i = imap.get(0); 
     i = i + 1; 
     System.out.println(imap.get(0)); 

     tmap = new HashMap<Integer, Thing>(); 
     tmap.put(0,new Thing(0)); 
     Thing t = tmap.get(0); 
     t.a = t.a + 1; 
     System.out.println(tmap.get(0).a); 
    } 
} 

class Thing{ 
    public int a; 
    public Thing(int n){ 
     this.a = n; 
    } 
} 

打印出以下幾點:

0 
1 

我希望它打印或者兩者的人(如果我修改參考)或兩個零(如果我正在修改值)。那麼爲什麼對於從整數到整數的映射,從整數到事物的行爲不同?

回答

5

Java的整數類型不可變,因此您的第一個示例從地圖獲取值,然後用新值替換本地變量。但是,第二個示例從地圖獲取對Thing實例的引用。

+0

你的意思是說int不可變,還是Integer? – ohq 2011-03-13 22:47:32

+0

如果我沒有記錯,兩者(就像String一樣)。 – 2011-03-13 22:51:09

+4

實際上,如果對象是不可變的,那並不重要。如果你做了'X x = map.get(0); x = somethingElse;',如果'X'是不可變的,那並不重要。你正在重新分配一個局部變量,它不會改變原來的'x'中的任何東西。 – 2011-03-13 22:57:36

1

通過執行i = i + 1,您不是遞增存儲在映射中包含的java.lang.Integer中的值。

+0

是的,這都是關於參考的,寶貝:是改變地圖中物體屬性的代碼。 – 2011-03-13 22:42:24

0

我想i = i + 1;將不會在對象上更新,因爲在您分配給基元時get將按值複製。原始更新因此不會反映在地圖中,因爲您沒有參考。通過Thing中的下一個例子,您直接分配給Thing的公共基元,所以再次按值 - 但是您更新了公共int。

+0

即使在將int i = imap.get(0)更改爲Integer i = imap.get(0)之後,我仍然得到0作爲第一個打印語句的結果 – ohq 2011-03-13 22:45:44

+0

通過對對象執行+我認爲您自動複製它到一個int。雖然我可能是錯的。 – Jim 2011-03-13 22:48:18

+0

不,它不是:將它改爲i = new Integer(i + 1)沒有任何區別。 – ohq 2011-03-13 22:50:24

0

這是因爲當您從第一個映射(通過將整數分配給int)抓取它時,您將自動拆箱Integer值。此時,您不使用Integer引用,而是使用int基元,與映射中保存的Integer引用沒有任何關係。因爲java整數是不可變的,所以沒有辦法做你想在這裏演示的東西。無法修改由映射中整數引用保持的內部基元int。你必須輸入一個新的整數來改變鍵值爲0的值。

0

回答問題的第二部分(「但是爲什麼它會在第二個打印語句中打印1?」),這是因爲行...

Thing t = tmap.get(0); 
t.a = t.a + 1; 

...讓你到位於給定位置的散列映射中的對象的引用,然後修改的成員變量的引用對象的。然後,println語句使用now-modified成員變量檢索對同一對象的另一個引用。

相關問題