Tôi có một vài câu hỏi về các kí hiệu chung trong Java:Java Generics (ký tự đại diện)
sự khác biệt giữa
List<? extends T>
vàList<? super T>
là gì?Ký tự đại diện bị chặn là gì và ký tự đại diện không bị ràng buộc là gì?
Tôi có một vài câu hỏi về các kí hiệu chung trong Java:Java Generics (ký tự đại diện)
sự khác biệt giữa List<? extends T>
và List<? super T>
là gì?
Ký tự đại diện bị chặn là gì và ký tự đại diện không bị ràng buộc là gì?
Trong câu hỏi đầu tiên, <? extends T>
và <? super T>
là ví dụ về ký tự đại diện bị chặn. Một ký tự đại diện không bị ràng buộc trông giống như <?>
và về cơ bản có nghĩa là <? extends Object>
. Nó có nghĩa là loại generic có thể là bất kỳ loại nào. Một ký tự đại diện bị chặn (<? extends T>
hoặc <? super T>
) đặt một giới hạn đối với loại này bằng cách cho biết rằng phải có mở rộng một loại cụ thể (<? extends T>
được gọi là giới hạn trên) hoặc phải là tổ tiên của một loại cụ thể (<? super T>
) được gọi là giới hạn dưới).
Hướng dẫn Java có một số giải thích khá tốt về generics trong các bài viết Wildcards và More Fun with Wildcards.
Chỉ cần làm đúng, nếu A là sai? –
Nếu bằng A để giới hạn lựa chọn của bạn là A hoặc B. –
và trong đó trường hợp nếu tôi nói super C> sự khác biệt là gì? –
Nếu bạn có một hệ thống phân cấp lớp A, B là một lớp con của A, và C và D cả hai đều là lớp con của B như dưới đây
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
Sau đó
List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();
List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile
public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}
public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}
Một kí hiệu wildcard bao cũng giống như ? extends B
trong đó B là một số loại. Đó là, loại không rõ nhưng một "ràng buộc" có thể được đặt trên đó. Trong trường hợp này, nó được bao quanh bởi một số lớp, mà là một lớp con của B.
+1 cho ví dụ! –
ví dụ tuyệt vời, cảm ơn bạn – Peter
Josh Bloch cũng có một lời giải thích tốt khi sử dụng super
và extends
trong google io video talk này nơi ông đề cập đến Nhà sản xuất extends
Consumer super
mnemonic .
Từ các slide thuyết trình:
Giả sử bạn muốn thêm các phương pháp số lượng lớn cho
Stack<E>
void pushAll(Collection<? extends E> src);
- src là một nhà sản xuất E
void popAll(Collection<? super E> dst);
- dst là một người tiêu dùng E
Tôi đã đọc cuốn sách của Bloch, nhưng tôi vẫn không thể thấy sự khác biệt giữa mở rộng và siêu trong trường hợp cụ thể này. –
Xem video, tôi nghĩ nó khá rõ ràng. Ngoài ra, tôi nghĩ bạn nên hỏi một câu hỏi khác về điều này "sự khác biệt giữa Danh sách extends T> và Danh sách super T>" nơi bạn hy vọng sẽ nhận được nhiều câu trả lời hơn. (nếu bạn có, hãy thêm một liên kết từ đây) – blank
Giường - tại sao không bao gồm ví dụ trong câu trả lời này để hoàn thành và đứng một mình. Liên kết là tạm thời. –
Có thể đôi khi bạn sẽ muốn hạn chế các loại được phép chuyển cho thông số loại. Ví dụ, một phương thức hoạt động trên các số có thể chỉ muốn chấp nhận các cá thể của Number hoặc các lớp con của nó. Đây là những thông số kiểu được bao bọc cho.
Collection<? extends MyObject>
có nghĩa là nó có thể chấp nhận tất cả đối tượng người có IS-Một mối quan hệ với MyObject (ví dụ:bất kỳ đối tượng nào là một loại myObject hoặc chúng ta có thể nói bất kỳ đối tượng nào của bất kỳ lớp con nào của MyObject) hoặc một đối tượng của lớp MyObject.
Ví dụ:
class MyObject {}
class YourObject extends MyObject{}
class OurObject extends MyObject{}
Sau đó,
Collection<? extends MyObject> myObject;
sẽ chỉ chấp nhận MyObject hoặc con cái của MyObject (tức là bất kỳ đối tượng kiểu OurObject hoặc YourObject hoặc MyObject, nhưng không phải bất kỳ đối tượng của lớp cha của MyObject).
Nói chung,
Nếu một cấu trúc chứa các yếu tố với một loại hình thức
? extends E
, chúng tôi có thể nhận được các yếu tố ra khỏi cơ cấu, nhưng chúng tôi không thể đặt yếu tố vào cấu trúc
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]");
Để đặt các yếu tố vào cấu trúc, chúng tôi cần một loại ký tự đại diện khác được gọi là Wildcards with super
,
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
Ký tự đại diện chung được tạo để tạo các phương thức hoạt động trên Bộ sưu tập có thể sử dụng lại nhiều hơn. Ví dụ: nếu phương thức có thông số List<A>
, chúng tôi chỉ có thể cung cấp cho List<A>
phương pháp này. Đó là một sự lãng phí cho Chức năng của phương pháp này trong một số trường hợp:
List<A>
, sau đó chúng ta nên được phép cung cấp cho List<A-sub>
đến phương pháp này. (Vì A-sub LÀ A)List<A>
, thì chúng tôi phải được phép cung cấp List<A-super>
cho phương pháp này. (Bởi vì A là A-super)Ví dụ, chúng tôi đã sau phân cấp lớp
Object < - Một < - B, C
Bạn nên sử dụng List <? extends A>
(trên bị ràng buộc) nếu bạn định truy cập đọc từ danh sách
Khi bạn biết rằng các cá thể trong bộ sưu tập là các cá thể của A hoặc các lớp con của A, nó là an toàn để đọc các phiên bản của bộ sưu tập và đưa chúng vào các phiên bản A.
Bạn không thể chèn thành phần vào danh sách, vì bạn không biết danh sách có được nhập vào loại A, B hay C.
Bạn nên sử dụng List <? super A>
(thấp hơn giới hạn) nếu bạn đang đi để chèn vào danh sách
Khi bạn biết rằng danh sách được đánh máy hoặc là A, hoặc một lớp cha của A, nó là an toàn để chèn trường hợp của A hoặc các lớp con của A (ví dụ: B hoặc C) vào danh sách.
Bạn không thể đọc từ danh sách, ngoại trừ nếu nó biểu diễn đối tượng đã đọc đối tượng. Các phần tử đã có trong danh sách có thể thuộc bất kỳ kiểu nào là A hoặc siêu lớp của A, nhưng không thể biết chính xác lớp đó là gì.
đọc thêm ở đây - http://tutorials.jenkov.com/java-generics/wildcards.html
Trong trường hợp đó [Ted Gao của] (http://stackoverflow.com/users/970122/ted-gao) [câu trả lời] (http://stackoverflow.com/a/9446233/2476755) bị xóa (vì nó chỉ là liên kết), đây là [bài đăng blog] (http://ted-gao.blogspot.com/search/label/Java%20Generics) mà nó được liên kết . – royhowie