instanceof.md 4.2 KB
Newer Older
沉默王二's avatar
沉默王二 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
---
category:
  - Java核心
tag:
  - Java
---

# Java instanceof关键字用法


instanceof 关键字的用法其实很简单:

```java
(object) instanceof (type)
```

用意也非常简单,判断对象是否符合指定的类型,结果要么是 true,要么是 false。在反序列化的时候,instanceof 操作符还是蛮常用的,因为这时候我们不太确定对象属不属于指定的类型,如果不进行判断的话,就容易抛出 ClassCastException 异常。

我们来建这样一个简单的类 Round:

```java
class Round {
}
```

然后新增一个扩展类 Ring:

```java
class Ring extends Round {
}
```

这时候,我们就可以通过 instanceof 来检查 Ring 对象是否属于 Round 类型。

```java
Ring ring = new Ring();
System.out.println(ring instanceof Round);
```

结果会输出 true,因为 Ring 继承了 Round,也就意味着 Ring 和 Round 符合 ` is-a` 的关系,而 instanceof 操作符正是基于类与类之间的继承关系,以及类与接口之间的实现关系的。

我们再来新建一个接口 Shape:

```java
interface Shape {
}
```

然后新建 Circle 类实现 Shape 接口并继承 Round 类:

```java
class Circle extends Round implements Shape {
}
```

如果对象是由该类创建的,那么 instanceof 的结果肯定为 true。

```java
Circle circle = new Circle();
System.out.println(circle instanceof Circle);
```

这个肯定没毛病,instanceof 就是干这个活的,大家也很好理解。那如果类型是父类呢?

```java
System.out.println(circle instanceof Round);
```

结果肯定还是 true,因为依然符合 `is-a` 的关系。那如果类型为接口呢?

```java
System.out.println(circle instanceof Shape);
```

结果仍然为 true, 因为也符合 `is-a` 的关系。如果要比较的对象和要比较的类型之间没有关系,当然是不能使用 instanceof 进行比较的。

为了验证这一点,我们来创建一个实现了 Shape 但与 Circle 无关的 Triangle 类:

``` java
class Triangle implements Shape {
}
```

这时候,再使用 instanceof 进行比较的话,编译器就报错了。

```java
 System.out.println(circle instanceof Triangle);
```

错误信息如下所示:

```
Inconvertible types; cannot cast 'com.itwanger.twentyfour.instanceof1.Circle' to 'com.itwanger.twentyfour.instanceof1.Triangle'
```

意思就是类型不匹配,不能转换,我们使用 instanceof 比较的目的,也就是希望如果结果为 true 的时候能进行类型转换。但显然 Circle 不能转为 Triangle。

编译器已经提前帮我们预知了,很聪明。

Java 是一门面向对象的编程语言,也就意味着除了基本数据类型,所有的类都会隐式继承 Object 类。所以下面的结果肯定也会输出 true。

```java
Thread thread = new Thread();
System.out.println(thread instanceof Object);
```

“那如果对象为 null 呢?”三妹这时候插话了。

“这个还真的是一个好问题啊。”我忍不住对三妹竖了一个大拇指。

```java
System.out.println(null instanceof Object);
```

只有对象才会有 null 值,所以编译器是不会报错的,只不过,对于 null 来说,instanceof 的结果为 false。因为所有的对象都可以为 null,所以也不好确定 null 到底属于哪一个类。

通常,我们是这样使用 instanceof 操作符的。

```java
// 先判断类型
if (obj instanceof String) {
    // 然后强制转换
    String s = (String) obj;
    // 然后才能使用
}
```

先用 instanceof 进行类型判断,然后再把 obj 强制转换成我们期望的类型再进行使用。

JDK 16 的时候,instanceof 模式匹配转了正,意味着使用 instanceof 的时候更便捷了。

```java
if (obj instanceof String s) {
    // 如果类型匹配 直接使用 s
}
```

可以直接在 if 条件判断类型的时候添加一个变量,就不需要再强转和声明新的变量了。

“哇,这样就简洁了呀!”三妹不仅惊叹到!

好了,关于 instanceof 操作符我们就先讲到这吧,难是一点都不难,希望各位同学也能够很好的掌握。

![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)