继承下类型转换分向上和向下:向上转型自动安全,如animal a = new dog();向下转型需instanceof校验再强转,否则抛classcastexception;父子数据类转换是字段映射而非类型转换;数组协变易致arraystoreexception,推荐泛型集合。

继承关系下的类型转换,核心是区分“向上”和“向下”两个方向,关键不在语法有多难,而在是否符合运行时对象的实际类型。转换能否成功,不看声明,而看内存里真正装的是什么。
向上转型:自动、安全、无需强转
子类对象赋值给父类引用,就是向上转型。Java 自动完成,不抛异常,也不需括号。
-
合法写法:
Animal a = new Dog();—— Dog 是 Animal 的一种,逻辑成立 - 此时
a只能调用Animal中定义的方法(含被重写的),不能直接访问Dog特有的方法如fetch() - 多态体现就在这里:调用
a.makeSound(),实际执行的是Dog重写的版本
向下转型:需显式强转,且必须运行时校验
把父类引用转回子类引用,是向下转型。编译器允许,但 JVM 运行时会检查——只有原对象真是那个子类实例,才成功;否则抛 ClassCastException。
-
安全写法:先用
instanceof判断,再强转if (a instanceof Dog) {<br> Dog d = (Dog) a;<br> d.fetch();<br>} -
危险写法:
Animal a = new Animal(); Dog d = (Dog) a;—— 编译通过,运行必崩 - Java 14+ 支持模式匹配简化:
if (a instanceof Dog d) { d.fetch(); },一步完成判断与赋值
父子字段/数据类的转换:不是类型强转,而是数据映射
当涉及 @Data 或 @Dataclass 类型(如 Java Lombok / Python dataclass),父子类之间没有“引用转型”一说,而是字段级的数据搬运。
- 父 → 子:把父类字段值 + 子类特有字段一起传入子类构造器,避免硬编码字段名(Python 可用
asdict();Java 可借助 Builder 模式或 Map 构造) - 子 → 父:只取父类声明的字段名对应值,丢弃子类独有字段(Python 可筛
Parent.__annotations__.keys();Java 可反射读取父类 declared fields) - 这类转换本质是新建对象,不是类型转换,也不改变原实例的类型
数组与集合的继承转换:特别容易踩坑
数组支持协变(Dog[] 可赋给 Animal[]),但运行时做元素写入检查,极易触发 ArrayStoreException。
-
Dog[] dogs = new Dog[2]; Animal[] animals = dogs;—— 合法 -
animals[0] = new Cat();—— 运行时报错,因底层仍是Dog[]数组 - 推荐用泛型集合替代数组:
List<animal></animal>可存任意子类,但不可写入非 Animal 实例,类型更安全











