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

Java遍历父类ArrayList时如何调用子类重写的toString方法

问题说明

我在父类和子类中分别重写了toString()方法,希望遍历元素类型为父类的ArrayList集合时,若集合中存储的是子类实例,则调用子类重写的toString()方法输出内容。

示例代码

父类实现:

public class SuperClass{
    // field
    String name;
    // methods 
    public SuperClass(String name) {
        this.name = name;
    }
    @override
    public String toString() {
        return "Name: " + name;
    }
}

子类实现:

public class SubClass extends SuperClass {
    // field 
    private int age;
    // methods
    public SubClass(String name, int age) {
        super(name);
        this.age = age;
    }
    @override
    public String toString() {
        return "Name: " + name +
               "\nAge: " + age;
    }
}

遍历逻辑所在类:

import java.util.ArrayList;

public class MyList {
    protected ArrayList<SuperClass> list = new ArrayList<>(); // display with Name and Age

    public void userInput() {
        // user inputting
        SubClass sub1 = new SubClass("Joe Black", 21);
        SubClass sub2 = new SubClass("Jane Black", 20);
        SuperClass sup1 = new SuperClass("Adam");
        list.add(sub1);
        list.add(sub2);
        list.add(sup1);
    }

    public void print() {
        for (SuperClass e : list) {
            System.out.println(e); // uses print methods of SuperClass or SubClass
        }
    }

    public static void main(String args[]) {
        MyList theList = new MyList();
        theList.userInput();
        theList.print();
    }
}

预期输出

$ javac SubClass.java SuperClass.java MyList.java
$ java -cp . MyList                              
Name: Joe Black
Age: 21
Name: Jane Black
Age: 20
Name: Adam
$ 

实际异常输出

$ javac SubClass.java SuperClass.java MyList.java
$ java -cp . MyList                              
Name: Joe Black
Name: Jane Black
Name: Adam
问题根因

这个需求完全可以实现,是Java多态动态分派的标准支持场景。现在输出不符合预期的核心原因是:你并没有在子类中成功重写toString()方法。
你代码里最明显的笔误是将重写校验注解@Override写成了@override(首字母小写)。Java对标识符大小写敏感,@Override是java.lang包下的内置注解,作用是在编译期校验当前方法是否符合重写规则;写成小写后,要么编译直接报错(无自定义同名注解的前提下),要么会掩盖方法签名不匹配的问题,导致你定义的子类toString()是一个独立的新方法,而非重写父类的方法,遍历的时候自然只会调用父类的实现。

修复步骤
  • 修正所有重写方法上的注解,将小写开头的@override改为标准大写开头的@Override。修正后如果方法签名不符合重写要求,编译器会直接报错,从根源上避免重写失效的问题。
    修正后的父类、子类toString()方法示例:
    // 父类和子类的toString方法上都用正确的@Override注解
    @Override
    public String toString() {
        // 方法实现保持原有逻辑即可
    }
    
  • 检查所有子类的toString()方法签名,必须和父类继承自Object的toString()完全一致:方法名为全小写的toString、参数列表为空、返回值为String类型、访问修饰符为public,不能用static/private/final修饰。
  • 不需要修改print()方法的遍历逻辑。System.out.println(Object o)会自动调用传入对象的toString()方法,JVM会根据对象的实际类型动态分派对应的方法实现:如果元素是子类实例就自动调用子类重写的toString(),如果是父类实例就调用父类的实现。后续新增其他子类时,只要正确重写toString(),不需要修改遍历逻辑就能自动适配输出,符合多态的设计特性。
验证结果

修正后重新编译运行,即可得到预期输出。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:30:39