我正在使用arraylist中的上限外卡(?)。当我使用通配符声明一个arraylist时,它无法正常工作。 例如 : 我有三个班级:
1)人员类:
public class Person {
}
2)延伸人的员工类:
public class Employee extends Person {
}
3)扩展员工的部门课程。
public class Dept extends Employee{
}
现在我想要将这三个类的对象添加到一个单独的类中的arraylist中,如下所示。
public class TestPerson {
public static void main(String[] args) {
Person p1 =new Person();
Employee e1 = new Employee();
Dept d1 = new Dept();
ArrayList<? extends Person> al =new ArrayList<Person>();
al.add(p1);
al.add(e1);
al.add(d1);
}
}
代码中的最后三行显示以下错误: 在ArrayList类型中添加(capture#1-of?extends Person)的方法不适用于参数(对象类型)。
但是来自#34;类型的arraylist?延伸人&#34;,可以采取&#34;任何对象延伸人&#34; ,但为什么它不接受扩展的员工对象 人
答案 0 :(得分:1)
ArrayList<? extends Person>
可以是ArrayList<Employee>
。在这种情况下,您将不被允许添加非员工。由于编译器不知道类型,因此它不允许您添加任何内容。
请注意,编译器 知道列表中已有的所有元素都是Person
的子类。因此,即使get
没有,add
仍有效:
Person x = al.get(0);
如果您想要List
可以选择三种类型之一,请使用ArrayList<Person>
。
答案 1 :(得分:1)
java泛型使用 Erasure 的概念实现,这意味着当您使用泛型时,任何特定的类型信息都会被删除。在内部泛型中,您实际上使用的是对象,例如列表(列表&lt; String&gt;)和列表(列表&lt;整数&gt; )在运行时是相同类型的。泛型类型仅在静态类型检查期间出现,之后程序中的每个泛型类型都被擦除,将其替换为非泛型上限强>
由于删除只删除类型信息,您可以调用 无界泛型参数的方法是对象的方法,但如果您可以约束参数是类型的子集,然后您可以调用该子集中的方法。要执行此约束,java泛型使用 extends 关键字。
鉴于此背景,当您指定ArrayList(ArrayList&lt;?extends Person&gt;)时,您实际上是指“从Person继承的任何类型的列表”。这并不意味着该列表将包含任何类型的人。通配符(?)引用了明确的类型,因此它表示此列表未指定的某些特定类型(Person类型)将在列表中。因此,列表可以包含特定类型的人,但您不知道哪一个是那个。因此,您无法将此类型的对象添加到此列表中。
但是,当你说ArrayList(?super Person)时,你说这个列表包含派生自Person的特定对象,即基础或超类型为Person的对象。因此,将Person或派生自Person的任何内容传递到此列表中是安全的。因此它有效。
希望有所帮助!