tuyên bố
Cameron Skinner trên rằng "đảm bảo Collections.unmodifiableMap rằng bản đồ sẽ không được sửa đổi" thực sự là chỉ phần đúng nói chung, mặc dù nó sẽ xảy ra là chính xác cho các ví dụ cụ thể trong câu hỏi (chỉ vì nhân vật đối tượng là không thay đổi). Tôi sẽ giải thích với một ví dụ.
Bộ sưu tập.unmodifiableBản đồ thực sự chỉ cung cấp cho bạn bảo vệ rằng tài liệu tham khảo đối với các đối tượng được giữ trong bản đồ không thể thay đổi. Nó làm điều đó bằng cách hạn chế 'đưa' vào bản đồ mà nó trả về. Tuy nhiên, bản đồ đóng gói ban đầu vẫn có thể được sửa đổi từ bên ngoài lớp vì Collections.unmodifiableMap không tạo ra bất kỳ bản sao nào của nội dung của bản đồ.
Trong câu hỏi được đăng bởi Paulo, các đối tượng Ký tự được giữ trong bản đồ may mắn không thể sửa đổi được. Tuy nhiên, nói chung điều này có thể không đúng và tính không thể sửa đổi được quảng cáo bởi Collections.unmodifiableMap không nên là biện pháp bảo vệ duy nhất. Ví dụ, xem ví dụ bên dưới.
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() + " ]"); }
}
Khi bạn chạy ví dụ này, bạn sẽ thấy:
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 ]
Các startingLocations bản đồ được đóng gói và chỉ trở lại bằng cách tận dụng Collections.unmodifiableMap trong phương pháp getStartingLocations. Tuy nhiên, lược đồ bị hủy bằng cách truy cập vào bất kỳ đối tượng nào và sau đó thay đổi nó, như được thấy trong phần "Thử 2" trong đoạn mã trên. Đủ để nói rằng người ta chỉ có thể dựa vào Collections.unmodifiableMap để cung cấp cho một bản đồ thực sự unmodifiable NẾU các đối tượng tổ chức trong bản đồ là mình không thay đổi. Nếu không, chúng tôi muốn sao chép các đối tượng trong bản đồ hoặc hạn chế quyền truy cập vào các phương thức sửa đổi của đối tượng, nếu có thể.
Bạn không thích 'final'? –
cuối cùng sẽ không làm cho bản đồ không thay đổi được, chỉ là tham chiếu đến bản đồ. Bạn vẫn có thể gọi các phương thức (như 'put') trên các tham chiếu cuối cùng. –
Trong ví dụ này, 'final' là cần thiết. (Trừ khi '_typesMap' được đặt lại thành một bản đồ khác sau này ...) –