2009-05-16 36 views
6

Có cách nào để thực hiện việc triển khai sau theo cách an toàn không?Java Generics đặt trên Bản đồ <String,? mở rộng Danh sách <String>>

public void myMethod(Map<String, ? extends List<String>> map) 
{ 
    map.put("foo", Collections.singletonList("bar"); 
} 

Triển khai trên không hoạt động. Nó yêu cầu Map<String, ? super List<String>> để biên dịch phương thức map.put() chính xác. Nhưng myMethod sẽ không chấp nhận bất kỳ subtype nào của List theo cách này. Vì vậy, tôi phải sử dụng Map<String, ? extends List<String>> để thay thế. Làm thế nào tôi có thể giải quyết vấn đề này một cách an toàn?

Trả lời

20
public void myMethod(Map<String, List<String>> map) { 
    map.put("foo", Collections.singletonList("bar")); 
} 

Bạn không thể đặt một List (kiểu trả về của Collections.singletonList() thành một Map của ? extends List từ các loại thực tế có thể là bất kỳ thực hiện List. Ví dụ, nó là không an toàn để đặt một generic List thành một Map<String,LinkedList> kể từ khi List có thể không phải một LinkedList. Tuy nhiên, chúng ta có thể dễ dàng đặt một LinkedList thành một Map của <String,List>.

tôi nghĩ rằng bạn w ere hơn suy nghĩ generics của bạn. Bạn không phải sử dụng ? extends cho một lớp học không chung chung. Ví dụ: List<Object> sẽ giữ bất kỳ Object, không cần thiết ? extends để thêm đối tượng. A List<List<Foo>> sẽ chỉ chụp List<Foo> đối tượng chứ không phải List<FooSubclass> đối tượng [Lớp chung không kế thừa dựa trên thông số của chúng]. Đây là nơi ? extends được phát. Để thêm cả hai List<Foo>List<FooSubclass> vào một số List, loại phải là List<List<? extends Foo>>.

+2

+1 để có giải thích tốt (giờ đây bạn có thể nhìn thấy generics của mình: P). –

+0

Rất tiếc. Tôi tiếp tục nghĩ rằng vì SOF lọc văn bản anyway rằng nó sửa chữa các công cụ khung góc cạnh. À ... – KitsuneYMG

6

Sẽ không Map<String, List<String> hoạt động? Có một số lý do cụ thể bạn phải có một ký tự đại diện ở đó?

0

Hãy tưởng tượng nếu ai đó đã vượt qua bạn Map<String, ArrayList<String>>. Giá trị bạn đặt vào là kết quả của Collections.singletonList là không phải là an ArrayList.

Bạn không thể chấp nhận bất kỳ loại phụ nào trong Danh sách trong Bản đồ và sau đó hy vọng có thể thêm loại phụ của riêng bạn, có thể không tương thích.

4

Có một nguyên tắc rất đơn giản khi sử dụng Bộ sưu tập và Generics cùng nhau. Nó được gọi là "Nguyên tắc Nhận và Đặt":

Sử dụng ký tự đại diện "mở rộng" khi bạn chỉ GET giá trị trong bộ sưu tập, sử dụng ký tự đại diện "siêu" khi bạn chỉ PUT giá trị vào bộ sưu tập và không sử dụng bất kỳ ký tự đại diện nào khi bạn muốn cả hai nhận và đặt.

Vì vậy, như bạn thấy, ví dụ ban đầu là không hợp lệ, theo nguyên tắc này.

Các vấn đề liên quan