卡梅倫Skinner的上述聲明說:「Collections.unmodifiableMap保證地圖將不會被修改」,實際上是隻一般部分如此,儘管它正好是準確的具體示例中的問題,(只因爲性格對象是不可變的)。我會用一個例子來解釋。
Collections.unmodifiableMap實際上只給你保護引用地圖中保存的對象不能更改。它通過限制'放入'它返回的地圖。但是,原始封裝映射仍然可以從類外部修改,因爲Collections.unmodifiableMap不會生成映射內容的任何副本。
在Paulo發佈的問題中,地圖中保存的Character對象幸運地不可修改。但是,一般情況下這可能並非如此,Collections.unmodifiableMap所宣傳的不可修改性不應該是唯一的保障。例如,請參閱下面的示例。
import java.awt.Point;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SeeminglyUnmodifiable {
private Map<String, Point> startingLocations = new HashMap<>(3);
public SeeminglyUnmodifiable(){
startingLocations.put("LeftRook", new Point(1, 1));
startingLocations.put("LeftKnight", new Point(1, 2));
startingLocations.put("LeftCamel", new Point(1, 3));
//..more locations..
}
public Map<String, Point> getStartingLocations(){
return Collections.unmodifiableMap(startingLocations);
}
public static void main(String [] args){
SeeminglyUnmodifiable pieceLocations = new SeeminglyUnmodifiable();
Map<String, Point> locations = pieceLocations.getStartingLocations();
Point camelLoc = locations.get("LeftCamel");
System.out.println("The LeftCamel's start is at [ " + camelLoc.getX() + ", " + camelLoc.getY() + " ]");
//Try 1. update elicits Exception
try{
locations.put("LeftCamel", new Point(0,0));
} catch (java.lang.UnsupportedOperationException e){
System.out.println("Try 1 - Could not update the map!");
}
//Try 2. Now let's try changing the contents of the object from the unmodifiable map!
camelLoc.setLocation(0,0);
//Now see whether we were able to update the actual map
Point newCamelLoc = pieceLocations.getStartingLocations().get("LeftCamel");
System.out.println("Try 2 - Map updated! The LeftCamel's start is now at [ " + newCamelLoc.getX() + ", " + newCamelLoc.getY() + " ]"); }
}
當你運行這個例子,你會看到:
The LeftCamel's start is at [ 1.0, 3.0 ]
Try 1 - Could not update the map!
Try 2 - Map updated! The LeftCamel's start is now at [ 0.0, 0.0 ]
的startingLocations映射封裝並僅在getStartingLocations方法利用Collections.unmodifiableMap返回。然而,通過訪問任何對象然後改變它,這個方案被顛覆了,如上面代碼中的「嘗試2」所示。只需說一個人只能依靠Collections.unmodifiableMap來給出一個真正不可修改的地圖,如果地圖中的對象本身是不可變的。如果他們不是,我們想要複製地圖中的對象,或者如果可能的話,限制對對象修飾符方法的訪問。
來源
2014-03-03 20:12:18
Don
你不喜歡'final'嗎? – 2010-10-22 17:01:35
最終將不會使地圖不可變,只會引用地圖。您仍然可以在最終引用上調用方法(如'put')。 – 2010-10-22 17:04:55
在這個例子中,'final'是必要的。 (除非'_typesMap'稍後重置爲不同的地圖...) – 2010-11-28 12:13:13