【问题标题】:Why can't I assign an Employee instance to ArrayList<? super Manager>? [duplicate]为什么我不能将 Employee 实例分配给 ArrayList<?超级经理>? [复制]
【发布时间】:2022-02-26 23:02:01
【问题描述】:

鉴于Manager extends Employee

当我尝试将 Employee 添加到经理的 ArrayList 时,我很惊讶地发现编译器错误,

   ArrayList<? super Manager> sonsOfEmployee = new ArrayList<>();
    sonsOfEmployee.add(new Employee("Manager",100000));

我得到错误

Required type: capture of ? super Manager

【问题讨论】:

  • ArrayList&lt;? super Manager&gt; sonsOfEmployee = new ArrayList&lt;Manager&gt;(); 编译。如果MangerEmployee子类型,那么您不能将Employee 添加到List&lt;Manager&gt; 是有道理的,不是吗?
  • @LouisWasserman 请仔细看问题。它不是 List
  • 我确实仔细看了这个问题。就 Java 而言,ArrayList&lt;? super Manager&gt;可能ArrayList&lt;Manager&gt;,这就是它不允许此分配的原因。
  • @LouisWasserman 那么为什么我们不能在ArrayList&lt;Manager&gt; 中添加Employee?毕竟它符合我们设定的规则:? super Manager 是允许的。
  • 欢迎您提出有关这些的问题,但是我在上一条评论中给出的代码示例是这不起作用的原因。

标签: java


【解决方案1】:

下界泛型集合 (Collection&lt;? super A&gt;) 可写 - 没错。

首先,让我们检查一下我们可以分配给它的集合类型。

List&lt;? super Manager&gt; 表示您可以为该列表分配经理列表、员工列表、对象列表。所有这些赋值都是完全有效的,它们都会编译:

List<? super Manager> list;
list = new ArrayList<Manager>();
list = new ArrayList<Employee>();
list = new ArrayList<Object>();

这意味着在list 的内部可以出现这些列表中的任何一个。我们只知道它可能是Manager 类型或其超类型的列表。如果它是 ArrayList&lt;Manager&gt;,则不能将 Employee 对象放入此集合中。

我们可以将Manager 的实例放入Collections&lt;Employee&gt;,但反过来不行。

让我们考虑另一个例子

ArrayList<? super String> list1 = new ArrayList<>();
list1.add((CharSequence) "Java"); // that will not compile
    
ArrayList<? super CharSequence> list2 = new ArrayList<>();
list2.add("Java");

CharSequence 类型的对象添加到ArrayList&lt;? super String&gt; 将无法编译,因为接口CharSequenceString 的超类型。

但我们可以在ArrayList&lt;? super CharSequence&gt; 中添加一个字符串,因为StringCharSequence 类型兼容。

【讨论】:

  • 我不明白你的句子 - 它不是一个 Arraylist。它是一个 ArrayLis,其中包含 Manager 的 surttype...,即 Employee。你说,“如果它是一个 ArrayList,你就不能把一个 Employee 对象放到这个集合中。”
  • Charsequence 作为 String 的超类型不是遵循规则吗? [Alexander]“将 CharSequence 类型的对象添加到 ArrayList 将无法编译,因为接口 CharSequence 是 String 的超类型。”
  • @likejudo 你误会了。 ArrayList&lt;? super String&gt; 不是实际类型。简单来说,泛型提供了一种告诉编译器类型我们不知道类型是什么的方法。 &lt;T&gt;通配符 不是真正的类型。 ArrayList&lt;? super String&gt; 仅存在于源代码中。所有通用信息都将替换为类型转换。该过程称为generic erasure
  • @likejudo 在运行时,我们将有一个ArrayList&lt;Manager&gt;ArrayList&lt;String&gt;(技术上是一个ArrayList,它维护Object[] 哪些元素将被转换为StringManager 类型时我们在这个集合上调用get())。
  • 遵循PECS规则ArrayList&lt;? super String&gt;即使我添加了String超类型的实例,也会失败?
猜你喜欢
  • 1970-01-01
  • 2017-07-31
  • 1970-01-01
  • 2017-03-28
  • 2019-02-08
  • 2017-07-20
  • 2012-11-10
  • 1970-01-01
相关资源
最近更新 更多