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
相关产品推荐
相关产品推荐

