Java Generics (Wildcards)
关于Java中的通用通配符,我有两个问题:
什么是有界通配符,什么是无界通配符?
在第一个问题中,
Java教程对文章通配符中的泛型有很好的解释,并且通配符也更有趣。
如果您有一个类层次结构a,b是a的子类,c和d都是b的子类,如下所示
1 2 3 4 | class A {} class B extends A {} class C extends B {} class D extends B {} |
然后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | List<? extends A> la; la = new ArrayList(); 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 } |
号
有界通配符类似于
Josh Bloch还很好地解释了在这个Google IO视频谈话中何时使用
在演示幻灯片中:
Suppose you want to add bulk methods to
Stack
void pushAll(Collection extends E> src); – src is an E producer
void popAll(Collection super E> dst); – dst is an E consumer
号
有时您可能希望限制允许传递给类型参数的类型的类型。例如,对数字进行操作的方法可能只希望接受数字或其子类的实例。这就是有界类型参数的用途。
1 | Collection<? extends MyObject> |
意味着它可以接受所有与MyObject有关系的对象(即任何属于MyObject类型的对象,或者我们可以说任何MyObject子类的对象)或MyObject类的对象。
例如:
1 2 3 4 5 | class MyObject {} class YourObject extends MyObject{} class OurObject extends MyObject{} |
。
然后,
1 | Collection<? extends MyObject> myObject; |
只接受myObject或myObject的子对象(即任何类型为ourObject或yourObject或myObject的对象,但不接受myObject的超类对象)。
一般来说,
If a structure contains elements with a type of the form
? extends E , we can get elements out of the structure, but we cannot put
elements into the structure
号
1 2 3 4 5 6 | 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]"); |
。
要将元素放入结构中,我们需要另一种称为
1 2 3 4 5 6 7 8 9 10 | 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)); } } |
。
预先要求
1 2 3 4 5 6 |
问题
1 2 | listB = listA; //not compiled listA = listB; //not compiled |
。
目的
When creating reusable methods that operate on collections of a
specific type.
号
如果要从列表中读取.get(),则应使用
When you know that the instances in the collection are of instances of A or subclasses of A, it is safe to read the instances of the collection and cast them to A instances.
You can not insert elements into the list, because you don't know if the list is typed to the class A, B or C.
号
如果要在列表中插入.add(),则应使用
When you know that the list is typed to either A, or a superclass of A, it is safe to insert instances of A or subclasses of A (e.g. B or C) into the list.
You cannot read from the list though, except if it casts the read objects to Object. The elements already present in the list could be of any type that is either an A or superclass of A, but it is not possible to know exactly which class it is.
号
请阅读更多内容-http://tutorials.jenkov.com/java-generics/widcards.html
创建通用通配符是为了使对集合操作的方法更可重用。
例如,如果一个方法有一个参数