You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将子类对象存入父类数组后,如何调用子类专属方法?

解决Java父类数组调用子类专属方法的问题

嘿,这个问题是Java里向上转型后非常常见的场景——当你把子类对象存入父类型数组时,编译器只会把数组元素识别为父类Person类型,自然没法直接调用子类独有的showStudentInfo()和showEmployeeInfo()方法。咱们有两种靠谱的解决方式,一起来看看:

方式一:向下转型(强制类型转换)

既然数组里的对象实际是子类类型,那咱们可以先判断对象的真实类型,再把它强制转换成对应的子类类型,这样就能调用子类专属方法了。

修改后的Demo代码

public class Demo {
    public static void main(String[] args) {
        Person ivan = new Person("Ivan Georgiev", 27, true);
        Person nikola = new Person("Nikola Ivanov", 30, true);
        Student iskra = new Student("Iskra Dimitrova", 21, false, 4.5);
        Student georgi = new Student("Georgi Kazakov", 19, true, 5.5);
        Employee neli = new Employee("Anelia Stoicheva", 35, false, 50);
        Employee monika = new Employee("Monika Petrova", 42, false, 80);

        // 先计算加班工资,不然showEmployeeInfo里的extraSum会是默认0
        neli.calculateOvertime(2);
        monika.calculateOvertime(3);

        Person[] array = new Person[6];
        array[0] = ivan;
        array[1] = nikola;
        array[2] = iskra;
        array[3] = georgi;
        array[4] = neli;
        array[5] = monika;

        // 用增强for循环更简洁
        for (Person person : array) {
            if (person instanceof Student) {
                // 向下转型为Student,调用子类方法
                Student student = (Student) person;
                student.showStudentInfo();
            } else if (person instanceof Employee) {
                // 向下转型为Employee,调用子类方法
                Employee employee = (Employee) person;
                employee.showEmployeeInfo();
            } else {
                // 父类Person对象,调用父类方法
                person.showPersonInfo();
            }
        }
    }
}

关键点说明

  • 用instanceof关键字判断对象的实际类型,这比你原来用getClass().equals()更常用,也更灵活(它会考虑继承关系)
  • 转型后必须是对象的真实类型,不然会抛出ClassCastException异常,所以一定要先判断再转型
  • 额外提一句:你原来的Employee类里的showEmployeeInfo()依赖extraSum,这个值需要调用calculateOvertime()才能生成,所以遍历前记得先调用这个方法赋值哦

方式二:利用多态(更优雅的方案)

如果想避免频繁的类型判断和转型,咱们可以利用Java的多态特性——在父类定义一个通用的方法,子类重写这个方法,这样遍历时直接调用父类方法就会自动触发子类的实现。

步骤1:修改父类Person,添加通用方法

public class Person {
    String name;
    int age;
    boolean isMan;

    Person(String name, int age, boolean isMan) {
        this.name = name;
        this.age = age;
        this.isMan = isMan;
    }

    // 定义通用的展示信息方法,子类重写
    void showInfo() {
        System.out.println("Име: " + this.name + " | " + "години: " + this.age + " | " + "мъж ли е: " + this.isMan);
    }
}

步骤2:子类重写showInfo方法

Student类:

public class Student extends Person {
    double score;

    Student(String name, int age, boolean isMan, double score) {
        super(name, age, isMan);
        this.score = score;
    }

    @Override
    public void showInfo() {
        // 修复你原来代码里多余的竖线问题
        System.out.println("Име: " + super.name + " | " + "години: " + super.age + " | " + "мъж ли е: " + super.isMan + " | " + "Оценка: " + this.score);
    }
}

Employee类:

public class Employee extends Person {
    double daySallary;
    double extraSum;

    Employee(String name, int age, boolean isMan, double daySallary){
        super(name, age, isMan);
        this.daySallary=daySallary;
    }

    double calculateOvertime(double hours) {
        if (this.age < 18) extraSum = 0;
        else extraSum = (this.daySallary / 8) * hours * 1.5;
        return extraSum;
    }

    @Override
    public void showInfo() {
        // 同样修复多余竖线问题
        System.out.println("Име: " + super.name + " | " + "години: " + super.age + " | " + "мъж ли е: " + super.isMan + " | " + "Допълнителна сума от оставане след работно време: " + this.extraSum);
    }
}

步骤3:简化Demo的遍历代码

public class Demo {
    public static void main(String[] args) {
        Person ivan = new Person("Ivan Georgiev", 27, true);
        Person nikola = new Person("Nikola Ivanov", 30, true);
        Student iskra = new Student("Iskra Dimitrova", 21, false, 4.5);
        Student georgi = new Student("Georgi Kazakov", 19, true, 5.5);
        Employee neli = new Employee("Anelia Stoicheva", 35, false, 50);
        Employee monika = new Employee("Monika Petrova", 42, false, 80);

        neli.calculateOvertime(2);
        monika.calculateOvertime(3);

        Person[] array = new Person[6];
        array[0] = ivan;
        array[1] = nikola;
        array[2] = iskra;
        array[3] = georgi;
        array[4] = neli;
        array[5] = monika;

        // 直接调用showInfo,多态会自动匹配子类实现
        for (Person person : array) {
            person.showInfo();
        }
    }
}

这种方式的好处

  • 完全不需要类型判断和转型,代码更简洁
  • 符合开闭原则:以后新增子类时,只需要重写showInfo()方法,不用修改遍历的逻辑,维护起来更轻松

另外,顺便提一下你原来代码里的小瑕疵:Student的showStudentInfo()方法里,"мъж ли е: "后面多了一个多余的" | ",会导致输出出现空的竖线段,我在上面的代码里已经修复了这个问题~

内容的提问来源于stack exchange,提问作者Nikolay Todorov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:24:25