逆变集合为什么只允许检索 Object 实例?

huangapple go评论60阅读模式
英文:

Why do contravariant collections only allow Object instances to be retrieved?

问题

在下面的示例中,“Apple”是可以添加到数组的任何内容的超类型。在下面的示例中,“Apple”或其任何子类型都可以添加到列表中。然而,只允许检索“Object”实例。由于只允许添加Apple及其子类型,为什么Java不允许将值映射到“Apple”实例?

class Fruit {
   @Override
   public String toString() {
      return "我是水果!!";
   }
}

class Apple extends Fruit {
   @Override
   public String toString() {
      return "我是苹果!!";
   }
}

class AsianApple extends Apple {
   @Override
   public String toString() {
      return "我是亚洲苹果!!";
   }
}

public class GenericsExamples {
   public static void main(String[] args) {
      //苹果列表
      List<Apple> apples = new ArrayList<Apple>();
      apples.add(new Apple());
       
      //我们可以将苹果列表分配给苹果篮子
      List<? super Apple> basket = apples;
       
      basket.add(new Apple());       //成功
      basket.add(new AsianApple());  //成功
      basket.add(new Fruit());       //编译时错误
      basket.add(new Object());      //编译时错误

      Object fruit1 = basket.get(0); //可行
      Apple appleFruit = basket.get(0); //编译器错误
   }
}
英文:

In the below example "Apple" is the super type of anything that can be added to the array. In the example below "Apple" or any of its subtypes are allowed to be added to the list. However only "Object" instances are allowed to be retrieved. Since only Apple and it's subtypes are allowed , why doesn't Java allow the values to be mapped to "Apple" instances?

class Fruit {
   @Override
   public String toString() {
      return &quot;I am a Fruit !!&quot;;
   }
}
 
class Apple extends Fruit {
   @Override
   public String toString() {
      return &quot;I am an Apple !!&quot;;
   }
}
 
class AsianApple extends Apple {
   @Override
   public String toString() {
      return &quot;I am an AsianApple !!&quot;;
   }
}
 
public class GenericsExamples
{
   public static void main(String[] args)
   {
      //List of apples
      List&lt;Apple&gt; apples = new ArrayList&lt;Apple&gt;();
      apples.add(new Apple());
       
      //We can assign a list of apples to a basket of apples
      List&lt;? super Apple&gt; basket = apples;
       
      basket.add(new Apple());      //Successful
      basket.add(new AsianApple()); //Successful
      basket.add(new Fruit());      //Compile time error
      basket.add(new Object());     //Compile time error

      Object fruit1 = basket.get(0); //works
      Apple appleFruit = basket.get(0); // compiler error
   }
}

答案1

得分: 2

也许你误解了List&lt;? super Apple&gt;的含义。通过它,你完全可以做如下操作:

List&lt;? super Apple&gt; apples = new ArrayList&lt;Object&gt;();

我现在肯定不能从apples中获取Apple对象,对吧?

因为在编译时Java并不知道apple实际上是什么类型(是ArrayList&lt;Object&gt;还是ArrayList&lt;Apple&gt;?),所以它不允许你从中获取Apple对象。

List&lt;? super Apple&gt;的目的是允许你将任何类型的List放入apples变量中,只要该类型是Apple或其父类。正因为如此,你可以将特定类型(Apple或其子类)的对象放入此列表中,但从中获取的只能是Object类型。

英文:

Perhaps you misunderstood what List&lt;? super Apple&gt; means. With it, you can totally do something like this:

List&lt;? super Apple&gt; apples = new ArrayList&lt;Object&gt;();

I can certainly not get Apples from apples now, can I?

Since Java doesn't know at compile time what apple actually is (Is it a Arraylist&lt;Object&gt; or ArrayList&lt;Apple&gt;?), it can't allow you to get Apples out of it.

The point of List&lt;? super Apple&gt; is to allow you to put any type of List into the apples variable, as long as that type is Apple or one of its superclasses. Because of this, it is limited what you can put into this list (Apple or its subclass) and what you can get out of it (Object only).

huangapple
  • 本文由 发表于 2020年10月13日 09:27:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/64327245.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定