instanceof关键字及其新特性

当在程序中执行向下转型操作时,如果父类对象不是子类对象的实例,就会发生 ClassCastException 异常,因此在执行向下转型之前需要养成一个良好的习惯,就是判断父类对象是否为子类对象的实例。这个判断通常使用 instanceof 关键字来完成。可以使用 instanceof 关键字判断是否一个类实现了某个接口(接口会在第7.8节中进行讲解),也可以用它来判断一个实例对象是否属于一个类。

instanceof 的语法格式如下:

myobject instanceof ExampleClass
  • myobject:某类的对象引用。

  • ExampleClass:某个类。

使用 instanceof 关键字的表达式返回值为布尔值。如果返回值为 true,则说明 myobject 对象为 ExampleClass 的实例对象;如果返回值为 false,则说明 myobject 对象不是 ExampleClass 的实例对象。

instanceof 是 Java 语言的关键字,Java 语言中的关键字都为小写。

下面来看一个向下转型与 instanceof 关键字结合的例子。

【例7.7】分析几何图形之间的继承关系(实例位置:资源包\TM\sl\7\7)

创建 Quadrangle 四边形类、Square 正方形类和 Circular 圆形类。其中,Square 类继承 Quadrangle 类,在主方法中分别创建这些类的对象,然后使用 instanceof 关键字判断它们的类型并输出结果。

class Quadrangle { }

class Square extends Quadrangle { }

class Circular { }

public class Demo5 {
	public static void main(String args[]) {
		Quadrangle q = new Quadrangle(); 	// 四边形对象
		Square s = new Square();			// 正方形对象
		// 判断四边形是否为正方形的子类
		System.out.println(q instanceof Square);
		// 判断正方形是否为四边形的子类
		System.out.println(s instanceof Quadrangle);
		// 由于正方形是否为圆形的子类
		System.out.println(q instanceof Circular);
	}
}

本实例在运行之前,Eclipse 就会报出如图7.5所示的编译错误。

image 2024 02 29 17 46 51 930
Figure 1. 图7.5 使用instanceof关键字发生的编译错误

由于四边形类与圆形类没有继承关系,因此二者不能使用 instanceof 关键字进行比较,否则会发生 “不兼容” 错误。如果删除或注释掉这行代码,则运行结果如下:

     false
     true

Java 14 为 instanceof 关键字提供了一个新特性:instanceof 模式匹配。那么,应该如何理解 “instanceof模式匹配” 呢?下面通过一个示例予以说明。

已知现有一个表示 “平行四边形类” 的 Quadrangle 类、一个表示 “圆环类” 的 Circular 类和一个用于测试 Test 类。在 Quadrangle 类和 Circular 类中都包含一个用于获取图形类别的 getCategory() 方法。在 Test 类中包含一个静态的、参数为 Object 类对象的 testGraphics() 方法,该方法用于检验 Object 类对象属于 “平行四边形类”,还是属于 “圆环类”。代码如下:

class Quadrangle {
    public String getCategory() {
        return "我属于平行四边形类";
    }
}

class Circular {
    public String getCategory() {
        return "我属于圆环类";
    }
}

public class Test {
    public static void main(String args[]) {
        Circular c = new Circular();
        testGraphics(c);
    }

    static void testGraphics(Object obj) {
        if (obj instanceof Quadrangle) {
            Quadrangle q = (Quadrangle) obj;
            System.out.println(q.getCategory());
        } else if (obj instanceof Circular) {
            Circular c = (Circular) obj;
            System.out.println(c.getCategory());
        }
    }
}

运行结果如下:

     我属于圆环类

从上述代码中不难看出,instanceof 确认成功后,还需要转换 Object 类对象的数据类型,才能调用相应类中的方法。使用 “instanceof模式匹配” 可以简化这个过程。关键代码如下:

static void testGraphics(Object obj) {
    if (obj instanceof Quadrangle q) {
        System.out.println(q.getCategory());
    } else if (obj instanceof Circular c) {
        System.out.println(c.getCategory());
    }
}

也就是说,使用 “instanceof模式匹配” 省去了 “转换Object类对象的数据类型” 的步骤。此外,instanceof 模式匹配的使用对象还被限定了作用域范围,使得程序更加安全。

编程训练(答案位置:资源包\TM\sl\7\编程训练)

【训练7】鸡是不是鸟? 判断“鸡是不是鸟”并阐明依据(因为鸡是鸟的子类,所以鸡是鸟)。

【训练8】总统是不是公务员? 通过instanceof判断总统是不是公务员,并输出公务员和总统的主要工作。