我正在准备Java7 Oracle证书,我想知道为什么Java以如此奇怪的方式处理switch-case:
public static void main(String[] args) {
int a = 2;
switch (a) {
case 0:
//System.out.println(b); // cannot find symbol variable b
break;
case 1:
boolean b=false;
break;
case 2:
b = true; // how case knows about existence of variable b?
break;
case 3:
//System.out.println(b); // var b might not have been initialized
break;
}
}
为什么案例0和案例3告知未知符号或未初始化变量,这是显而易见的,但我无法想象为什么案例2正常工作?如果在案例1中分配了b
,编译器如何知道?对我来说,这不是连贯的。
UPDATE1: 实际上更奇怪的是,在案例3中我注意到编译时错误(Linux64,Java7和Java8),但我的一些同事却没有。
我准备了非常简单的maven项目:https://github.com/gonciarz/switch-test
UPDATE2: 似乎对于每个人来说case3都没有编译。谢谢你们的澄清。
答案 0 :(得分:4)
您正在混淆声明和作业。在你的代码中
case 1:
boolean b=false;
break;
case 2:
b = true; // how case knows about existence of variable b?
break;
变量b
在case 1:
中被声明为和。 声明的范围是switch
语句块的其余部分,即最多}
。
就像你写的那样:
case 1:
boolean b;// declaration
b=false; // assignment
break;
分配对case 2:
标签的代码流无效。如果跳转到case 2
标签,则变量声明但已分配,因为可以跳过赋值但不能声明。
因此行为与您的第三个标签一致:
case 3:
System.out.println(b); // var b might not have been initialized
break;
此处,变量b
声明,但未分配。这就是错误消息告诉你的内容:它没有说b
未声明,但它“可能没有被初始化”,这包括你肯定知道它没有被初始化的可能性点。
b
的类型是声明的类型,不依赖于任何作业。
作为旁注,switch
和if
之间存在差异。你写过吗
final int a = 2;
boolean b;
if(a == 2) b=false;
System.out.println(b);
a
的常量性质导致编译器检测到b
将被分配给false
并且没有生成错误。这适用于if
,但不适用于switch
。
答案 1 :(得分:1)
这里的范围是整个switch子句,而不是单独的case。范围由{
和}
定义。
当您使用boolean b = false
声明变量时,可以在范围的其余部分(即switch子句的其余部分)中访问它。
您在问题中提到的案例3中没有出现错误。
编辑: 你做在案例3中得到一个错误,但似乎Eclipse在检测它时很草率。我混淆了字段声明,它获取了具有局部变量的基元的默认值。
答案 2 :(得分:1)
规则说明了这一点:
块中的局部变量声明的范围(第14.4节)是声明出现的块的其余部分,从其自己的初始化器开始,并包括局部变量声明语句中右侧的任何其他声明符。 / p>
和这个
声明在编译时处理,不依赖于代码的执行流程。由于value是在switch块的本地范围内声明的,因此从声明的角度来看,它可以在该块中的任何位置使用。