V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhao1014
V2EX  ›  Java

向父类类型化数组列表中添加子类对象。。。

  •  
  •   zhao1014 · 2019-09-10 13:30:39 +08:00 · 3698 次点击
    这是一个创建于 1936 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:定义了 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 条附言  ·  2019-09-10 15:50:42 +08:00
    感觉我对 java 编译 java 运行的概念还是很模糊啊。。。得加把劲了。。。
    9 条回复    2019-09-11 16:55:09 +08:00
    aguesuka
        1
    aguesuka  
       2019-09-10 13:41:01 +08:00 via Android
    比如有个 List<Object>,你可以把任意对象放进去,但是取出来的时候还是 Object,必须 cast 成你要的对象
    ayonel
        2
    ayonel  
       2019-09-10 14:21:10 +08:00
    取出来,用强制类型转换转成子类对象,即 Manager. 大概这样: (Manager) (staff.get(0)).setbonus;
    可以了解下 java 的编译时类型检查和运行时类型检查
    cigarzh
        3
    cigarzh  
       2019-09-10 14:38:47 +08:00
    编译器报错,你想想啊,staff 里既可以放 Employee 也可以放 Manager,编译器怎么知道你 get()出来的是 Employee 还是 Manager 呢,肯定不能让你 setBonus 啊
    zhao1014
        4
    zhao1014  
    OP
       2019-09-10 14:42:54 +08:00 via Android
    @aguesuka 看来我得补充一下有关泛型的知识。。。
    zhao1014
        5
    zhao1014  
    OP
       2019-09-10 14:43:27 +08:00 via Android
    @ayonel 感谢!确实需要了解一下
    zhao1014
        6
    zhao1014  
    OP
       2019-09-10 15:12:32 +08:00
    @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;这种的向上转型?
    zhao1014
        7
    zhao1014  
    OP
       2019-09-10 15:43:28 +08:00
    @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 方法了。。。。
    Aresxue
        8
    Aresxue  
       2019-09-11 10:19:08 +08:00   ❤️ 1
    泛型擦除。对于 JVM 来说他只认列表,不关心你列表是啥,统一擦除到上界(对应这里就是子类对象也会被认为是父类对象)
    zhao1014
        9
    zhao1014  
    OP
       2019-09-11 16:55:09 +08:00 via Android
    @Aresxue 受教了!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2064 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 01:05 · PVG 09:05 · LAX 17:05 · JFK 20:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.