instanceof 是什么?
instanceof 是 Java 的一个二元运算符(也叫关键字),它的作用是判断一个对象是否是某个特定类(或其子类、或某个接口)的实例。

它会检查对象在运行时(runtime)的实际类型,并判断这个类型是否与目标类型兼容。
语法
result = object instanceof Type
object:一个对象实例,通常是某个类的实例。Type:一个类名、接口名或一个数组类型。result:一个布尔值(boolean)。object是Type的实例,或者Type是object类的父类/父接口,则结果为true;否则为false。
重要提示:object 必须是一个对象引用(不能是基本数据类型),否则编译器会报错。
工作原理与示例
instanceof 的工作机制是基于继承关系的,一个对象被认为是其声明类型以及所有父类和实现的接口的实例。
示例 1:基本用法(类)
class Animal {}
class Dog extends Animal {}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
Dog myDog = new Dog();
// myDog 是 Animal 的实例吗?是的,因为 Dog 继承自 Animal。
System.out.println(myDog instanceof Animal); // 输出: true
// myDog 是 Dog 的实例吗?是的,它本身就是 Dog 类型的。
System.out.println(myDog instanceof Dog); // 输出: true
// myAnimal 是 Dog 的实例吗?不是,它只是 Animal 类型,不是 Dog 类型。
System.out.println(myAnimal instanceof Dog); // 输出: false
}
}
示例 2:接口
instanceof 也可以用来检查对象是否实现了某个接口。

interface Flyable {
void fly();
}
class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flying.");
}
}
class Car {}
public class Main {
public static void main(String[] args) {
Bird myBird = new Bird();
Car myCar = new Car();
// myBird 实现了 Flyable 接口吗?是的。
System.out.println(myBird instanceof Flyable); // 输出: true
// myCar 实现了 Flyable 接口吗?没有。
System.out.println(myCar instanceof Flyable); // 输出: false
}
}
示例 3:处理 null
instanceof 有一个非常重要的特性:object 是 null,instanceof 的结果永远是 false。
public class Main {
public static void main(String[] args) {
String myString = null;
// null 不是 String 的实例
System.out.println(myString instanceof String); // 输出: false
}
}
示例 4:数组
instanceof 也可以用来检查数组类型。
public class Main {
public static void main(String[] args) {
int[] intArray = new int[10];
String[] stringArray = new String[10];
Object obj = intArray;
// obj 是 int[] 类型吗?是的。
System.out.println(obj instanceof int[]); // 输出: true
// obj 是 String[] 类型吗?不是。
System.out.println(obj instanceof String[]); // 输出: false
// stringArray 是 Object 类型吗?是的,因为所有数组都是 Object 的子类。
System.out.println(stringArray instanceof Object); // 输出: true
}
}
instanceof 的实际应用场景
instanceof 最常见的应用场景是向下转型(Downcasting)前的安全检查,以避免发生 ClassCastException。
在 Java 5 之前,这是处理多态对象的标准方式。

示例:在向下转型前进行检查
class Animal {
public void eat() {
System.out.println("Animal is eating.");
}
}
class Dog extends Animal {
public void bark() {
System.out.println("Dog is barking.");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // 向上转型 (Upcasting)
// 如果不检查,直接转型,可能会在运行时出错
// Dog myDog = (Dog) myAnimal; // 这是可以的,因为 myAnimal 实际上是 Dog
Animal anotherAnimal = new Animal();
// Dog myDog2 = (Dog) anotherAnimal; // 这会抛出 ClassCastException
// 安全的做法:先 instanceof 检查,再转型
if (myAnimal instanceof Dog) {
// 只有在检查通过后,才进行转型
Dog myDog = (Dog) myAnimal;
myDog.bark(); // 现在可以安全地调用 Dog 的特有方法
} else {
System.out.println("myAnimal is not a Dog.");
}
}
}
Java 14 中的模式匹配(Pattern Matching for instanceof)
从 Java 14 开始,instanceof 增加了一个非常有用的模式匹配功能,这极大地简化了代码,避免了在检查后还要手动进行转型的麻烦。
旧式写法(Java 14 之前):
if (myAnimal instanceof Dog) {
Dog myDog = (Dog) myAnimal; // 手动转型
myDog.bark();
}
新式写法(Java 14+):
if (myAnimal instanceof Dog myDog) { // 在判断的同时,将转型后的对象赋值给 myDog
myDog.bark(); // 直接使用,无需手动转型
}
这种写法的优势:
- 代码更简洁:一行代码完成了类型检查和转型两个操作。
- 更安全:变量
myDog的作用域被限制在if语句块内,避免了在块外误用未正确转型的对象。 - 可读性更高:意图更加明确,清晰地表达了“
myAnimal是Dog类型,那么将其视为Dog并执行后续操作”。
编译时规则
instanceof 的类型检查在编译时也会进行一些校验,以确保类型的安全性。
-
不能用于基本数据类型:
instanceof只能用于对象引用。int num = 10; // System.out.println(num instanceof Integer); // 编译错误: Incompatible conditional operand types int and Integer
-
目标类型必须是可转换的:
object的类型必须是Type或其子类,或者Type是object实现的接口,否则编译会报错。class A {} class B {} A a = new A(); // System.out.println(a instanceof B); // 编译错误: Incompatible conditional operand types A and B // 因为 A 和 B 之间没有继承或实现关系。
| 特性 | 描述 |
|---|---|
| 作用 | 判断一个运行时对象的类型是否与目标类型(类、接口、数组)兼容。 |
| 返回值 | boolean 类型。 |
| 语法 | object instanceof Type |
null 处理 |
object 是 null,结果永远是 false。 |
| 核心应用 | 在进行向下转型前进行安全检查,防止 ClassCastException。 |
| 现代用法 | Java 14+ 的模式匹配,将类型检查和转型合并为一行,使代码更简洁、安全。 |
| 编译时检查 | 目标类型必须与对象类型有继承或实现关系,否则编译失败。 |
instanceof 是 Java 多态和类型安全机制中非常重要的一环,理解它的用法对于编写健壮、可维护的 Java 代码至关重要。
