父类引用数组可存储不同子类对象,依赖向上造型与运行时多态:声明为Animal[]后可存Dog、Cat等实例;调用makeSound()自动执行各子类重写版本;访问子类特有成员需instanceof校验后强制转换。

父类引用数组能存不同子类对象,关键在于“向上造型”——子类对象可以自动当作父类类型来使用,编译器只检查类型兼容性,运行时才决定调用哪个具体实现。
声明和初始化要匹配父类类型
数组声明必须用父类(或接口)类型,但实际元素可以是任意子类实例:
- 正确写法:Animal[] animals = new Animal[3]; // 允许后续放入 Dog、Cat、Bird 等 Animal 的子类对象
- 错误写法:Dog[] dogs = new Dog[3]; animals = dogs; // 类型不兼容,不能直接赋值;但反过来,Dog 对象可放进 Animal[] 中
存入子类对象无需强制转换
只要子类继承自该父类(或实现对应接口),赋值就是安全的、隐式的:
- animals[0] = new Dog();
- animals[1] = new Cat();
- animals[2] = new Bird();
- 所有语句编译通过,JVM 在运行时记住每个位置上真实的对象类型
调用方法自动触发多态
遍历数组并调用重写方法时,JVM 根据每个元素的实际类型执行对应逻辑:
- for (Animal a : animals) { a.makeSound(); }
- 输出可能是:"汪汪汪" → "喵喵喵" → "啾啾啾"
- 不需要 if-else 判断类型,也不用手动分发逻辑
访问子类特有成员需谨慎转型
父类引用本身看不到子类新增字段或方法,要用 instanceof + 强制转换 才能安全使用:
- 比如想让 Dog 对象执行 fetch() 方法: if (a instanceof Dog) { ((Dog) a).fetch(); }
- 漏掉 instanceof 检查可能抛出 ClassCastException
- 接口方式(如 List
)在新增子类时更易扩展,推荐优先考虑

















