【Java】Java 16中不再需要进行instanceof后的类型转换
首先
当使用instanceof时,有时我们会像下面这样进行强制类型转换。
if (obj instanceof String) {
String s = (String) obj;
// do anything
}
听说从Java 16开始不需要强制类型转换了。
如果你知道那个的话,就不需要读以下内容了。
就会变成这样
这被称为 instanceof 模式匹配。
最初的代码可以写成如下的样子。
if (obj instanceof String s) {
// do anything
}
在这一行代码中,完成了以下操作。
-
- 如果obj是String类型,则将其转换为String类型
- 将其赋值给变量s(在这里我们称s为模式变量)
因此,在后续的处理中,可以使用s进行各种处理。
模式变量的范围
模式变量的作用域如下所述。
只有当编译器可以推断出模式一定匹配并且变量已经被赋值时,模式变量才处于作用域内。
只有在编译器能够确定模式匹配并给变量赋值的情况下,模式变量才会进入作用域。
换句话说,模式变量的作用范围只在变量被赋值并具有意义时才存在。(这被称为流程作用域,大概是这个意思)
例如,可以如下所示。
public class Sample {
void foo(Object obj) {
// (1)
if (obj instanceof String a) {
// objがString型の場合、パターン変数aのスコープ内
}
// (2)
if (obj instanceof Boolean a) {
// objがBoolean型の場合、パターン変数aのスコープ内
}
// パターン変数aのスコープ外
}
在这段代码中,使用了相同的模式变量a在(1)和(2)处。
如果使用instanceof匹配了类型,变量a将在各自的if代码块中有作用域,否则变量a就没有作用域。
使用!后作用域相反。
public class Sample {
void foo(Object obj) {
if (!(obj instanceof String s)) {
// objはString型ではなくsのスコープ外
} else {
// objはString型でsのスコープ内
}
// sのスコープ外
}
}
再给一个样本吧!
public class Sample {
void foo(Object obj) {
if (!(obj instanceof String s)) {
throw new IllegalArgumentException("Must be a string");
}
// sのスコープ
var s = "hoge"; // コンパイルエラー
}
}
在 `if` 语句结束后,保证了作用域变量 `s` 是 `String` 类型,所以 `if` 语句之后成为了 `s` 的作用域。
因此,如果试图重新声明 `s`,将会出现编译错误。
此外,即使会引发异常,如果不抛出异常,则无法保证 s 是 String 类型,因此可以将其声明为超出作用域。
顺便提一句
可以通过变量屏蔽(在重叠的作用域中使用相同名称的变量,使得低级作用域的变量覆盖高级作用域的变量)来操作字段变量。
class Example {
String s;
void test(Object o) {
if (o instanceof String s) {
System.out.println(s); // shadowing
s = s + "\n";
}
System.out.println(s);
}
}
当使用以下代码运行时,将显示hoge,null。
public class Main {
public static void main(String[] args) {
Example e = new Example();
e.test("hoge");
}
}
用途
例如,我认为在Java 16之前,有时候需要使用equals来编写如下的代码。
public class Foo {
int i;
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Foo)) {
return false;
}
// instanceofで確認した後にキャスト
Foo other = (Foo) obj;
if (other.i != this.i) {
return false;
}
return true;
}
}
这是一个equals方法,如果Foo对象的变量i相等,则返回true。
这样↓可以写成↑。
public class Foo {
int i;
@Override
public boolean equals(Object obj) {
return (obj instanceof Foo other) && other.i == this.i;
}
}
最後
如果有任何错误或需要补充的地方,请大家提出指正,感激不尽。