Menu
CoddyTech

instanceof 运算符

本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 31 课,共 87 课。

上一课说明了,如果对象实际上不是你要转换成的类型,下转型可能会因 ClassCastException 而失败。instanceof 运算符可以让你在转换前检查对象的类型,从而解决这个问题。

语法很简单:如果对象是该类(或其任意子类)的实例,object instanceof ClassName 就会返回 true:

Animal animal = new Dog();

if (animal instanceof Dog) {
    Dog dog = (Dog) animal;
    dog.bark();  // 可以安全地调用 Dog 类特有的方法
}

这个检查可以确保类型转换成功,从而避免运行时错误。对于继承层级中的父类型,该运算符也会返回 true:

Dog dog = new Dog();
System.out.println(dog instanceof Dog);     // true
System.out.println(dog instanceof Animal);  // true
System.out.println(dog instanceof Object);  // true

从 Java 16 开始,你可以使用模式匹配,一步完成检查和类型转换:

if (animal instanceof Dog dog) {
    dog.bark();  // 'dog' 已完成类型转换,可以直接使用
}

这种更简洁的语法省去了单独的类型转换语句。请注意,使用 instanceof 检查 null 时会返回 false,因此你不需要单独检查 null。

challenge icon

挑战

简单

我们来构建一个车辆检查系统,使用 instanceof 运算符安全地识别和处理不同类型的车辆。你将创建一个车辆类层次结构,并编写代码,在访问车辆的专属功能前检查车辆的实际类型。

你需要将代码分成 4 个文件:

  • Vehicle.java:创建所有车辆共用的基类。每辆车都有一个 model 字段(String)。添加一个用于初始化该字段的构造函数、一个 getter 方法 getModel(),以及一个打印以下内容的方法 inspect():Inspecting vehicle: [model]
  • Car.java:创建一个继承 Vehicle 的类。汽车还有一个额外的 numDoors 字段(int)。使用 super 初始化父类。添加一个打印以下内容的方法 checkDoors():[model] has [numDoors] doors
  • Motorcycle.java:创建另一个继承 Vehicle 的类。摩托车有一个 hasSidecar 字段(boolean)。添加一个方法 checkSidecar(),根据布尔值打印 [model] has a sidecar 或 [model] has no sidecar。
  • Main.java:这里就需要用到 instanceof 了!你会收到 4 个输入:汽车型号、车门数量、摩托车型号,以及是否带有边斗(true/false)。

    创建一个 Vehicle 引用数组,其中包含一辆 Car 和一辆 Motorcycle。然后循环遍历数组,对每辆车执行以下操作:

    • 调用基类的 inspect() 方法
    • 使用 instanceof 检查它是否是 Car,如果是,就安全地向下转型并调用 checkDoors()
    • 使用 instanceof 检查它是否是 Motorcycle,如果是,就安全地向下转型并调用 checkSidecar()

你会收到 4 个输入:汽车型号(String)、车门数量(int)、摩托车型号(String)以及是否带有边斗(boolean)。

输出应包含 4 行:每辆车都会先显示检查信息,然后显示对应类型的检查结果。instanceof 运算符可以确保你只对 Car 调用 Car 的方法,只对 Motorcycle 调用 Motorcycle 的方法,从而避免 ClassCastException!

亲手试试

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 读取输入
        String carModel = scanner.nextLine();
        int numDoors = Integer.parseInt(scanner.nextLine());
        String motorcycleModel = scanner.nextLine();
        boolean hasSidecar = Boolean.parseBoolean(scanner.nextLine());
        
        // TODO: 用 carModel 和 numDoors 创建一个 Car 对象
        
        // TODO: 用 motorcycleModel 和 hasSidecar 创建一个 Motorcycle 对象
        
        // TODO: 创建一个包含 Car 和 Motorcycle 的 Vehicle 引用数组
        
        // TODO: 遍历数组,对每辆车执行以下操作:
        // 1. 调用 inspect() 方法
        // 2. 用 instanceof 检查它是否为 Car,然后向下转型并调用 checkDoors()
        // 3. 用 instanceof 检查它是否为 Motorcycle,然后向下转型并调用 checkSidecar()
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Java 在线编译器