向上转型是子类对象自动转为父类引用,安全且支持多态;向下转型需显式强转并配合instanceof校验,否则易抛ClassCastException。

向上转型就是子类对象当父类用,自动且安全
向上转型的本质是“用更宽泛的类型去引用更具体的对象”,比如 Dog 是 Animal 的子类,那么 Animal a = new Dog() 就是典型的向上转型。它不需要强制转换符号,编译器直接放行。
- 只能调用父类声明的方法和属性,哪怕子类重写了
eat(),调用时也走子类实现(多态生效) - 子类独有的方法(如
catchMouse()或bark())在转型后完全不可见,编译就报错:Cannot resolve method 'bark' in 'Animal' - 常见于集合统一管理、方法参数接收、返回值抽象化等场景,例如
Listpets = new ArrayList(); pets.add(new Dog()); pets.add(new Cat());
向下转型必须显式强转,不加 instanceof 很可能崩溃
当你已经向上转型过(比如拿到一个 Animal 引用),又想调用子类特有功能时,就得向下转型——但 Java 不信任你,必须你自己加括号写明目标类型,比如 (Dog) a。
- 如果
a实际指向的不是Dog(比如是Cat或纯new Animal()),运行时立刻抛出ClassCastException - 正确做法永远先用
instanceof安全校验:if (a instanceof Dog) {
Dog d = (Dog) a;
d.bark();
} - 别图省事写
Dog d = (Dog) a;然后靠 try-catch 捕获异常——这不是防御,是掩盖设计缺陷
为什么不能绕过 instanceof 直接强转
因为 JVM 在运行时才确定对象真实类型,而编译器只看引用类型。你声明的是 Animal a,编译器默认它可能是任意子类甚至就是 Animal 本身;强制转成 Dog 是在赌,而赌输的代价是程序中断。
-
instanceof是运行时类型检查指令,开销极小,现代 JVM 还会做优化 - 泛型擦除后,
List>或Object类型的容器取出来的元素,若需还原为具体子类,同样依赖instanceof+ 向下转型 - 替代方案?用枚举区分类型、用 Visitor 模式、或改用 sealed class(Java 17+)限制子类范围,但这些都解决不了“已存在父类引用需恢复子类能力”这个原始需求
容易被忽略的细节:null 值和泛型边界
instanceof 对 null 返回 false,所以 if (a instanceof Dog) 不会 NPE;但直接 (Dog) a 遇到 null 不会抛 ClassCastException,而是返回 null(即转型成功但结果为空),后续调用方法时才 NPE——这种延迟失败更难排查。
立即学习“Java免费学习笔记(深入)”;
- 泛型中如
List存了Dog,取出来仍是Animal类型,转型逻辑不变;但List extends Animal>取出的元素连instanceof都受限,得靠运行时类型信息(getClass())辅助判断 - 接口实现类之间的转型(如
IHuman h = new Man(); Man m = (Man) h;)规则完全一致,只是把“继承”换成“实现”关系
(Xxx) 之前,先问自己:这个引用真能保证是 Xxx 吗?如果不是,有没有更干净的设计方式?








