必须先用 instanceof 判断再强制转换,否则可能抛出 ClassCastException 或 NullPointerException;正确做法是先检查、再转换、后调用,Java 14+ 支持模式匹配简化该流程。

不能直接强制转换,必须先确保引用实际指向子类对象,否则会抛出 ClassCastException。核心是“安全向下转型”,关键在类型检查。
为什么要先用 instanceof 判断?
父类引用可能指向父类对象、任意子类对象,或 null。强行 (Sub)superRef 会崩溃——JVM 只在运行时验证实际类型,不看声明类型。
- 如果 superRef 实际是 Parent 类型或 null,(Sub)superRef 立即抛异常
- instanceof 在运行时检查堆中对象的真实 class,安全兜底
- 这是向下转型(downcast)的强制约定,不是可选项
正确写法:先检查,再转换,再调用
以 Animal 父类和 Dog 子类为例:
Animal a = getAnimal(); // 可能返回 Dog、Cat 或 Animal 实例
if (a instanceof Dog) {
Dog d = (Dog) a; // 安全转换
d.bark(); // 调用 Dog 特有方法
}
- 不要写成
Dog d = (Dog)a;然后 try-catch 异常——这不是健壮设计,是掩盖逻辑漏洞 - Java 14+ 可用模式匹配简化:
if (a instanceof Dog d) { d.bark(); },自动完成检查+转换+声明
避免转型的设计替代方案
频繁向下转型往往说明设计可优化:
立即学习“Java免费学习笔记(深入)”;
- 把特有行为提取为接口(如
Barkable),让 Dog 实现它,用if (a instanceof Barkable)判断 - 在父类定义 default 方法(如
makeSound()),子类重写,直接调用a.makeSound() - 用访问者模式或策略模式将行为外移,消除对具体类型的依赖
常见错误场景
这些代码一定会失败:
-
Animal a = new Animal(); Dog d = (Dog)a;→ ClassCastException -
Animal a = null; Dog d = (Dog)a;→ NullPointerException(转型前就空了) -
Animal a = new Cat(); Dog d = (Dog)a;→ ClassCastException(Cat 不是 Dog)


















