背景:定义了 Employeee 类 public class Employee { private String name; private double salary; private LocalDate hireDay; //........ Getter and Setter} 定义一个 Manager 类继承 Employee public class Manager extends Employee {
private double bonus;
//........
public void setBouns(double bouns) {
this.bonus = bouns;
}}
现在创建一个数组列表,ArrayList<employee> staff = new ArrayList<>(); 向列表中添加元素</employee>
staff.add(new Manager("狗蛋",1000,2019,9,10)); 向 staff 中添加 Manager 类是可行的 但是当我想 staff.get(0).setbonus;时却会报错 我想跟这是子类特有属性有关但不知道具体为什么 像是 staff.get(0).getSalary 什么的都是没有问题的 setbonus 却不行这是为什么 而且子类对象可以添加进父类对象的数组列表,我也不清楚为什么,有没有大佬解答?
1
aguesuka 2019-09-10 13:41:01 +08:00 via Android
比如有个 List<Object>,你可以把任意对象放进去,但是取出来的时候还是 Object,必须 cast 成你要的对象
|
2
ayonel 2019-09-10 14:21:10 +08:00
取出来,用强制类型转换转成子类对象,即 Manager. 大概这样: (Manager) (staff.get(0)).setbonus;
可以了解下 java 的编译时类型检查和运行时类型检查 |
3
cigarzh 2019-09-10 14:38:47 +08:00
编译器报错,你想想啊,staff 里既可以放 Employee 也可以放 Manager,编译器怎么知道你 get()出来的是 Employee 还是 Manager 呢,肯定不能让你 setBonus 啊
|
6
zhao1014 OP @cigarzh @aguesuka @ayonel
我本来想自己添加一个判断 Manager manager = new Manager("askdj",12312,2342,1,3);//参数为姓名,工资,入职日期的年月日 if (staff.get(3).getClass() == manager.getClass()){ staff.get(3).setbonus(1000); }//3 是 Manager 类对象的索引值 发现还是报错了。。 而且我开始是这么写的: Manager manager = staff.get(3)//这里还是报错了,提醒我必须要进行类型转换 正确写法应该是 Manager manager = (Manager)staff.get(3); 我还没有了解泛型的知识,这里应该是 Manger 类添加进 ArrayList<Employee>数组列表时被自动转换成 Employee 类了? 类似于 Employee e = new Manager;这种的向上转型? |
7
zhao1014 OP @aguesuka @ayonel @cigarzh
看了一下 get ()方法的源码 public E get(int index) { rangeCheck(index); return elementData(index); } 这里是先 rangeCheck 检查索引值是否溢出,溢出的话抛出一个异常 然后 return elementData(index); 我又看了一下 elementData();方法 @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; } 这里好像是从 elementData 数组中返回一个对象然后强制类型转换成了 E 类型,也就是我代码中的 Empolyee 类型? Employee 类型自然是不能调用 setBonus 方法了。。。。 |
8
Aresxue 2019-09-11 10:19:08 +08:00 1
泛型擦除。对于 JVM 来说他只认列表,不关心你列表是啥,统一擦除到上界(对应这里就是子类对象也会被认为是父类对象)
|