必须用 instanceof 校验再向下转型,否则易抛 classcastexception;它在运行时检查继承关系、对 null 返回 false,是类型安全的必要守门员。

向下转型前必须用 instanceof 做校验,否则极易触发 ClassCastException。它不是可选项,而是运行时类型安全的最低成本守门员。
为什么非用不可
编译器只认声明类型,不查实际类型。比如 Object obj = new Dog(),编译期只知道是 Object;真正调用 (Dog)obj.bark() 时,JVM 才检查——若 obj 实际是 Cat 或 null,立刻崩溃。
-
instanceof在运行时走对象的类继承链比对,支持父类、子类、接口实现关系 - 对
null返回false,不抛异常,天然防 NPE - 跳过它直接强转,等于把类型安全交给运气
标准写法与常见误区
正确结构是“先判、再转、后用”,三步不能合并或省略:
- ✅ 推荐(Java 14+):
if (obj instanceof Dog d) { d.bark(); }—— 一次完成判断、转型、绑定 - ✅ 兼容写法:
if (obj instanceof Dog) { Dog d = (Dog) obj; d.bark(); } - ❌ 危险写法:
Dog d = (Dog) obj;—— 没判断就强转,出错才暴露 - ❌ 伪安全写法:
if (obj != null && obj instanceof Dog)—— 多余判空,instanceof本身已处理null
泛型和接口场景的特别注意
泛型擦除和接口抽象性会让校验更易出错:
- 不能写
list instanceof List<string></string>,编译失败;只能写list instanceof List -
obj instanceof List为true,不代表(List<string>)obj</string>安全——得再检查元素:list.get(0) instanceof String - 接口检查(如
Runnable)只保证方法签名存在,不保证行为可用(例如代理对象可能抛UnsupportedOperationException)
替代方案与边界提醒
instanceof 解决的是“是不是”的问题,不是“能不能用”的问题:
- 需要运行时动态类型(如插件系统),可用
clazz.isInstance(obj),语义等价但支持变量传入 - 要严格匹配“就是这个类”,不用子类,才考虑
obj.getClass() == Dog.class;但多数业务应优先接受多态 - 别用
try-catch ClassCastException替代校验——异常开销大,且掩盖设计缺陷










