2011-11-03 44 views
26

正如我們所知道的,java中「final」關鍵字的用途。在將變量聲明爲final時,我們必須初始化變量。像「final int a = 10;」 我們無法更改「a」的值。但是如果我們使用HashTable,可能會添加一些值,甚至會將HashTable聲明爲final。在java中創建哈希表作爲final

例::

private static final Hashtable<String,Integer> MYHASH = new Hashtable<String,Integer>() 
{{  put("foo",  1);  
     put("bar",  256);  
     put("data",  3);  
     put("moredata", 27);  
     put("hello", 32);  
     put("world", 65536); }}; 

現在我宣佈MYHASH哈希表決賽。如果我試圖添加更多的元素,它接受。

MYHASH.put("NEW DATA",  256); 

現在「新數據」被添加到HashTable中。 我的問題是爲什麼它允許添加甚至聲明爲最終的????

+0

注意,如果地圖的內容是可變的('java.util.Date'或'java.awt.Point',說),那麼它仍然是可變的。 –

回答

63

因爲最終標記的是參考,而不是對象。您不能將該參考點設置爲不同的哈希表。但是你可以對該對象做任何事情,包括添加和刪除東西。

你的int的例子是一個原始類型,而不是一個引用。最後意味着你不能改變變量的值。因此,使用int,您無法更改變量的值,例如使int的值不同。使用對象引用時,不能更改引用的值,即指向哪個對象。

0

對於字段和變量,使用final表示它們只能分配一次。立即或稍後(例如在字段的構造函數中)。這並不意味着實際的實例變得不可變。 Hashtable是一個數據結構,您可以添加條目,而不管它是如何分配給某個變量的。只有參考是最終的。

6

嘗試使用Collections.unmodifiableMap(MYHASH )以不可修改的地圖包裹您的Hashtable。當您嘗試更改地圖中的某些內容時,這應該會引發異常,即添加或刪除條目。 (注意:MYHASH應該然後是類型Map<String, String>,而不是Hashtable<String, String>的。)

關於final關鍵字:像別人已經說過的,這意味着你不能指定其他HashtableMYHASH但地圖本身仍然是可變的。要改變這個,你必須用一些不可變的包裝器來包裝它,比如上面提到的UnmodifiableMap

12

只有引用是final的,它的方法當然可以像調用非final的引用一樣調用。使用Collections.unmodifiableMap(map)使地圖不可修改。

4

正如喬說的,這是因爲final標誌着參考不是對象。

但是,你可以做你想要Collections.unmodifiableMap(見here

8

您可以使用Collections.unmodifiableMap克服你的哈希表不可修改的包裝的東西。

例子:

import java.util.*; 
class Test{ 

    public static final Map<String,Integer> MYHASH; 
    static{ 
     Hashtable<String,Integer> tmp = 
      new Hashtable<String,Integer>(); 
     tmp.put("A",65); 
     tmp.put("C",67); 
     MYHASH = Collections.unmodifiableMap(tmp); 
    } 

    public static void main(String[] args){ 

     System.out.println(MYHASH.get("A")); 

     //this will throw 
     //java.lang.UnsupportedOperationException 
     MYHASH.put("B",66);  

    } 

} 
+1

你得到了我的+1,因爲你顯然沒有保留地圖的可變版本以防意外變異。本來希望保持不變的靜態'private'。使用'Hashtable'也沒有意義。 –

+0

謝謝!爲了與問題保持一致,我使用了「Hashtable」,但我沒有注意到「private」。 – Vlad

+0

謝謝你也解決了我的問題。 – bean