2013-07-08 46 views
5

Tôi có một câu hỏi liên quan Generics:chi tiết về "siêu" ký tự đại diện trong generics java

Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>(); 

với siêu nó có thể để nhanh chóng một HashMap<Object,Object> cho một <? super String>. Tuy nhiên, sau đó bạn có thể thêm các đối tượng chỉ mở rộng String (trong trường hợp này chỉ là String). Tại sao chúng không bị cấm bởi lỗi biên dịch cũng như xảy ra với ký tự đại diện extends. Ý tôi là nếu đã từng tạo Map <Object, Object> thì chỉ có thể thêm Chuỗi .. tại sao không bắt buộc phải tạo một Map<String, String> ngay từ đầu? (giống như nó xảy ra với ký tự đại diện extends)

Một lần nữa tôi biết sự khác biệt giữa superextends liên quan đến generics. Tôi chỉ muốn biết các chi tiết tôi đã đề cập đến.

Xin cảm ơn trước.

+1

Tuy nhiên sau đó bạn có thể thêm các đối tượng chỉ kéo dài chuỗi (trong trường hợp này chỉ Chuỗi chính nó) Bạn có thể thêm CharSequences và Object, không objets kéo dài chuỗi. – Nimajen

+0

@Nimajen được đề cập trong câu hỏi. – Rollerball

+0

xin lỗi, phím sai. Nhận xét của tôi chưa hoàn chỉnh. – Nimajen

Trả lời

2
Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>(); 

Kể từ Java Generics được dựa trên loại tẩy xoá, với dòng này bạn đã không tạo ra một MashMap<Object,Object>. Bạn vừa tạo một thể hiện của lớp HashMap; các tham số kiểu bị mất ngay lập tức sau dòng mã này và tất cả các biến đó là loại biến số mappa1 của bạn, thậm chí không đề cập đến Object. Loại biểu thức new tương thích với kiểu mappa1 do đó trình biên dịch cho phép gán.

Nói chung, các thông số loại được sử dụng với new không liên quan và để giải quyết vấn đề này, Java 7 đã giới thiệu toán tử kim cương <>. Tất cả những gì thực sự quan trọng là loại mappa1, là Map<? super String, ? super String>; như xa như phần còn lại của mã của bạn là có liên quan, đây là loại bản đồ instantiated.

+0

http://docs.oracle.com/javase/tutorial/java/generics/erasure.html Tuy nhiên trong liên kết đó nó nói: Rollerball

+0

Hơn nữa trong trường hợp ký tự đại diện "mở rộng", nó cũng phải được cho phép. Intead không thể tạo HashMap nếu tham chiếu là Map <. – Rollerball

+0

Tất nhiên nó không phải là: 'Object' không mở rộng' String'. –

0

Sự cố bạn mô tả không tồn tại. Đó là do tham chiếu của bạn được khai báo là Map<? super String, ? super String>. Nhưng đối tượng thực tế của bạn có thể chứa bất kỳ đối tượng vì nó HashMap<Object,Object>

Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>(); 
map1.put("", ""); 

//you can put only string to map1 

//but you can do this 
Map map2 = map1; 
map2.put(23, 234); 

cùng có thể được mô tả bằng một ví dụ tốt hơn:

String a = "a". 
a.length(); // legal. 

Object b = a; 
b.length() // compilation error 
+0

Nó không trả lời câu hỏi của tôi. Tôi không muốn biết cách giải quyết. Tôi chỉ muốn biết tại sao nó hoạt động như thế – Rollerball

+1

xin lỗi, Nó không phải là một cách giải quyết, đó là lời giải thích. Chuỗi chỉ là một lớp bình thường trong Java. Trình biên dịch không quan tâm cho dù đó là lớp Custom hay java.lang.String của bạn. – Tala

2

Tôi nghĩ bạn bị loại vì bạn đã chọn loại bộ sưu tập. Bộ sưu tập hiếm khi được sử dụng như người tiêu dùng và do đó một giới hạn dưới (? super X) không được đặt trên các loại phần tử của chúng. Một ví dụ thích hợp hơn là vị ngữ.

Xem xét phương thức như <E> List<E> filter(List<? extends E> p, Predicate<? super E> p). Nó sẽ lấy một danh sách l và một biến vị ngữ p và trả lại một danh sách mới chứa tất cả các thành phần của l đáp ứng p.

Bạn có thể chuyển vào số List<Integer>Predicate<Number> được tất cả các bội số của 2.5 hài lòng. Predicate<Number> sẽ trở thành Predicate<? super Integer>. Nếu không, bạn không thể gọi bộ lọc như sau.

List<Integer> x = filter(Arrays.asList(1,5,8,10), Predicates.multipleOf(2.5)); 
5

Hãy sử dụng List thay vì Map để ngắn gọn.

Về cơ bản, ý nghĩa thực tiễn của extendssuper thể được định nghĩa như sau:

  • List<? extends T> có nghĩa là "một List bạn có thể nhận T từ"
  • List<? super T> có nghĩa là "một List bạn có thể đặt T vào"

Bây giờ bạn có thể thấy rằng không có gì đặc biệt về extends - hành vi của extendssuper là hoàn toàn đối xứng:

List<? extends Object> a = new ArrayList<String>(); // Valid, you can get an Object from List<String> 
List<? extends String> b = new ArrayList<Object>(); // Invalid, there is no guarantee that List<Object> contains only Strings 

List<? super String> a = new ArrayList<Object>(); // Valid, you can put a String into List<Object> 
List<? super Object> b = new ArrayList<String>(); // Invalid, you cannot put arbitrary Object into List<String> 
Các vấn đề liên quan