Java从抽象类对象集合调用子类非抽象方法报错问题求解
报错原因与解决方案
报错核心原因
你遇到的报错是两个问题共同导致的:
- 你直接对
ArrayList<Component>类型的集合对象componentList调用setRadius()方法,ArrayList本身没有定义该方法,这是第一层错误。 - 就算你修正为取出集合中的元素调用
componentList.get(0).setRadius(50),依然会报错:你的集合泛型定义为父类Component,但setRadius()是子类ItemA独有的方法,父类Component中没有声明该方法,Java多态机制下父类引用无法直接调用子类独有的未在父类中定义的方法。
解决方法
根据你的业务场景可以选择以下三种方案:
方案1:向下转型调用(仅部分元素是ItemA的场景)
如果集合中同时存在ItemA、ItemB、ItemC三类元素,仅需要对ItemA类型的元素设置半径,先取出元素做类型判断后向下转型再调用方法:
public void domain() { componentList.add(new ItemA(25, 10)); // 取出下标为0的元素做类型校验,避免类型转换异常 if(componentList.get(0) instanceof ItemA) { ItemA targetItem = (ItemA) componentList.get(0); targetItem.setRadius(50); } }
方案2:父类新增抽象方法(所有子类都需要半径属性的场景)
如果ItemB、ItemC也有半径相关的属性需要设置,可以直接在Component抽象类中新增setRadius抽象方法,所有子类实现该方法后即可直接用父类引用调用:
public abstract class Component { protected String name; public abstract double getVolume(); // 新增抽象setRadius方法 public abstract void setRadius(int p_radius); // Getter and setter for name }
后续ItemB、ItemC同步实现setRadius方法即可。
方案3:调整集合泛型(集合仅存ItemA元素的场景)
如果你的集合只需要存储ItemA类型的元素,直接把集合泛型修改为ItemA即可直接调用独有方法:
public class domain { ArrayList<ItemA> componentList = new ArrayList<ItemA>(); public void domain() { componentList.add(new ItemA(25, 10)); componentList.get(0).setRadius(50); } }
附加代码优化提示
你提供的示例代码还存在几处语法问题需要修正:
- Java中字符串类型是大写开头的
String不是string - 圆周率需要用
Math.PI而不是直接写pi - ItemA未定义接收半径和高度的有参构造方法,需要补充后才能使用
new ItemA(25, 10)实例化对象
内容的提问来源于stack exchange,提问作者Jean Guydoune
相关产品推荐
相关产品推荐

