Ste*_*eve 10 java instanceof java-17
我正在阅读 Oracle 的官方文档来了解Java 17 中的模式变量范围。在以下示例中,该方法testScope1按照文档中的说明工作,但该方法testScope2给出了编译错误。我无法弄清楚为什么void该方法的返回类型会导致问题?
interface Vehicle{}
class Car implements Vehicle{}
class Pattern{
public int testScope1(Vehicle v){
if(!(v instanceof Car c)){
return 1;
}
System.out.println(c.toString()); //WORKS FINE
return 2;
}
public void testScope2(Vehicle v){
if(!(v instanceof Car c)){
}
System.out.println(c.toString()); //COMPILE TIME ERROR: Cannot resolve symbol c
}
}
Run Code Online (Sandbox Code Playgroud)
Bri*_*etz 12
模式变量(在模式中声明的绑定变量)使用流敏感的作用域。与普通局部变量不同,普通局部变量在连续区域的范围内,模式变量在其声明模式明确分配的范围内。
如果你有一个if声明:
if (x instanceof Foo(var v)) {
A;
}
else {
B;
}
Run Code Online (Sandbox Code Playgroud)
thenv位于 for 的范围内A,但不在 for 的范围内B,因为我们不能保证v在到达 的情况下会明确地为 分配一个值B。如果我们使用明显的重构来反转我们的测试:
if (!(x instanceof Foo(var v))) {
B;
}
else {
A;
}
Run Code Online (Sandbox Code Playgroud)
也是如此;v位于 范围内A,但不在范围内B。这些规则与局部变量的明确赋值规则完全相同——“如果我到达这一点,这个值是否保证已被赋值”。
其他条件结构,例如短路&&和||,也参与此范围界定。例如,以下内容是有效的:
if (x instanceof Foo(var v) && v != null) {
A;
}
Run Code Online (Sandbox Code Playgroud)
但以下不是:
if (x instanceof Foo(var v) || v != null) {
A;
}
Run Code Online (Sandbox Code Playgroud)
因为在后者中,v当我们到达该子句时,不能保证已被赋值v != null。
这些规则甚至包含非本地控制流,例如异常。例如,如果我们有:
if (!(x instanceof Foo(var v)) {
System.out.println("Not a Foo");
}
B(v);
Run Code Online (Sandbox Code Playgroud)
这将是一个错误,因为v当我们到达 时,不能保证已经被分配了一个值B(v),但是如果if块突然完成:
if (!(x instanceof Foo(var v)) {
throw new NotFooException();
}
B(v);
Run Code Online (Sandbox Code Playgroud)
thenv位于 at 范围内B(v),因为我们可以保证,如果到达该点,v则已被赋值。
if这可能看起来很复杂,但实际上非常简单:鉴于您对、等结构的流程控制的了解throw,模式变量是否保证在给定点被赋值?如果是这样,那么它就在那时的范围内。
想想如果不是v实例会发生什么:Car
testScope1,该return 1;语句导致该方法退出。该方法的后续语句不会被执行。一切都很好。testScope2\xe2\x80\x99s没有return,所以控制流达到c.toString()。但v\xe2\x80\x99t 不是一个Car,那么 \xe2\x80\xa6 是什么c?!它可以\xe2\x80\x99 不存在,因为它必须是某种类型,Car但\xe2\x80\x99 是一个反事实。这就是为什么您\xe2\x80\x99 收到错误\xe2\x80\x9c无法解析符号c\xe2\x80\x9d 的原因。| 归档时间: |
|
| 查看次数: |
1206 次 |
| 最近记录: |