Java 泛型(通配符)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/252055/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:02:04  来源:igfitidea点击:

Java Generics (Wildcards)

javagenericsbounded-wildcard

提问by Pablo Fernandez

I have a couple of questions about generic wildcards in Java:

我有几个关于 Java 中的通用通配符的问题:

  1. What is the difference between List<? extends T>and List<? super T>?

  2. What is a bounded wildcard and what is an unbounded wildcard?

  1. List<? extends T>和 和有List<? super T>什么区别?

  2. 什么是有界通配符,什么是无界通配符?

采纳答案by Bill the Lizard

In your first question, <? extends T>and <? super T>are examples of bounded wildcards. An unbounded wildcard looks like <?>, and basically means <? extends Object>. It loosely means the generic can be any type. A bounded wildcard (<? extends T>or <? super T>) places a restriction on the type by saying that it either has to extenda specific type (<? extends T>is known as an upper bound), or has to be an ancestor of a specific type (<? super T>is known as a lower bound).

在您的第一个问题中,<? extends T><? super T>是有界通配符的示例。无界通配符看起来像<?>,基本上意味着<? extends Object>。它松散地意味着泛型可以是任何类型。有界通配符 ( <? extends T>or <? super T>) 对类型施加限制,表示它要么必须扩展特定类型(<? extends T>称为上限),要么必须是特定类型的祖先(<? super T>称为下限) .

The Java Tutorials have some pretty good explanations of generics in the articles Wildcardsand More Fun with Wildcards.

Java 教程在通配符通配符更有趣的文章中对泛型有一些很好的解释。

回答by oxbow_lakes

If you have a class hierarchy A, B is a subclass of A, and C and D both are subclass of B like below

如果您有一个类层次结构 A,B 是 A 的子类,而 C 和 D 都是 B 的子类,如下所示

class A {}
class B extends A {}
class C extends B {}
class D extends B {}

Then

然后

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 
}

A bounded wildcard is like ? extends Bwhere B is some type. That is, the type is unknown but a "bound" can be placed on it. In this case, it is bounded by some class, which is a subclass of B.

有界通配符就像? extends BB 是某种类型。也就是说,类型是未知的,但可以在其上放置“绑定”。在这种情况下,它受某个类的限制,该类是 B 的子类。

回答by blank

Josh Bloch also has a good explanation of when to use superand extendsin this google io video talkwhere he mentions the Producer extendsConsumer supermnemonic.

Josh Bloch 也很好地解释了何时使用superextends在这个google io 视频演讲中,他提到了生产者extends消费者super助记符。

From the presentation slides:

从演示幻灯片:

Suppose you want to add bulk methods to Stack<E>

void pushAll(Collection<? extends E> src);

– src is an E producer

void popAll(Collection<? super E> dst);

– dst is an E consumer

假设你想添加批量方法到 Stack<E>

void pushAll(Collection<? extends E> src);

– src 是 E 生产者

void popAll(Collection<? super E> dst);

– dst 是 E 消费者

回答by Sandeep Kumar

There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.

有时您可能希望限制允许传递给类型参数的类型的种类。例如,对数字进行操作的方法可能只想接受 Number 或其子类的实例。这就是有界类型参数的用途。

Collection<? extends MyObject> 

means that it can accept all object who have IS- Arelationship with MyObject (i.e. any object which is a type of myObject or we can say any object of any subclass of MyObject) or a object of MyObject class.

意味着它可以接受所有与 MyObject有IS-A关系的对象(即任何属于 myObject 类型的对象,或者我们可以说 MyObject 的任何子类的任何对象)或 MyObject 类的对象。

For example:

例如:

class MyObject {}

class YourObject extends MyObject{}

class OurObject extends MyObject{}

Then,

然后,

Collection<? extends MyObject> myObject; 

will accept only MyObject or children of MyObject(i.e. any object of type OurObject or YourObject or MyObject, but not any object of superclass of MyObject).

将只接受 MyObject 或 MyObject 的子对象(即类型为 OurObject 或 YourObject 或 MyObject 的任何对象,但不接受 MyObject 超类的任何对象)。

回答by Prateek Joshi

In general,

一般来说,

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

如果一个结构包含具有 form 类型的元素? extends E,我们可以从结构中取出元素,但不能将元素放入结构中

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]"); 

To put elements into the structure we need another kind of wildcard called Wildcards with super,

要将元素放入结构中,我们需要另一种称为 的通配符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));
         }
    }

回答by taoxiaopang

Generic wildcards are created to make methods that operate on Collection more reusable.

创建通用通配符是为了使对 Collection 进行操作的方法更具可重用性。

For example, if a method has a parameter List<A>, we can only give List<A>to this method. It is a waste for this method's funtion under some circumstances:

例如,如果一个方法有一个参数List<A>,我们只能给List<A>这个方法。在某些情况下,这种方法的功能是一种浪费:

  1. If this method only reads objects from List<A>, then we should be allowed to give List<A-sub>to this method. (Because A-sub IS a A)
  2. If this method only inserts objects to List<A>, then we should be allowed to give List<A-super>to this method. (Because A IS a A-super)
  1. 如果这个方法只从 读取对象List<A>,那么我们应该被允许给List<A-sub>这个方法。(因为 A-sub 是 A)
  2. 如果这个方法只向 插入对象List<A>,那么我们应该允许给List<A-super>这个方法。(因为A是A超)