2011-11-03 41 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