必须用 instanceof 而非直接强转,当方法接收 Object 或父类参数但需调用子类特有行为时,否则会抛 ClassCastException;instanceof 对 null 恒返回 false,比 getClass() 更安全。

什么时候必须用 instanceof 而不是直接强转
当方法接收的是 Object 或父类类型参数,但内部逻辑依赖子类特有行为时,强转前必须先确认类型安全。否则运行时抛出 ClassCastException。
常见于集合遍历、回调参数、泛型擦除后的类型还原等场景。
- 错误写法:
(String) obj—— 若obj是Integer,立刻崩溃 - 正确写法:
if (obj instanceof String) { String s = (String) obj; ... } - 注意:JDK 14+ 支持模式匹配(
if (obj instanceof String s)),但老版本仍需显式声明变量
instanceof 对 null 的处理规则
instanceof 在左操作数为 null 时**恒返回 false**,不会抛异常。这是它比 getClass().equals() 更安全的关键点。
-
null instanceof String→false -
obj == null ? false : obj.getClass() == String.class才等价于instanceof的语义 - 别用
obj != null && obj.getClass() == Xxx.class替代 —— 它不识别子类,且对null需额外判空
和 Class.isInstance() 的实际差异
两者语义一致,但适用场景不同:instanceof 是编译期关键字,要求右侧必须是已知类/接口名;Class.isInstance() 接收 Class 对象,适合动态类型判断。
立即学习“Java免费学习笔记(深入)”;
- 静态类型已知 → 用
instanceof(更简洁、可读性强) - 类型来自配置、反射或泛型参数(如
clazz.isInstance(obj))→ 必须用isInstance() - 性能上无实质差别,JVM 都会做相同类型检查
在 record 和 sealed class 中的注意事项
JDK 14+ 的 record 和 JDK 17+ 的 sealed 类不影响 instanceof 基本行为,但容易忽略继承边界问题。
-
record Point(int x, int y) {}→new Point(1,2) instanceof Point为true,但不能instanceof其子类(record 不允许继承) -
sealed interface Shape permits Circle, Rect→shape instanceof Circle合法,但若未来新增子类而没更新判断逻辑,可能漏分支 - 搭配
switch(JDK 21+ 模式匹配)可避免漏判,但instanceof单独用时需人工保证覆盖全
instanceof 的价值不在语法糖,而在把运行时风险锁死在一次显式检查里——尤其当你无法控制上游传入的对象来源时。








