问题

我有一个关于Java交换机的疯狂问题。

int key = 2;
switch (key) {
case 1:
int value = 1;
break;
case 2:
value = 2;
System.out.println(value);
break;
default:
break;
}

场景1 - 当key为2时,它成功将值打印为2。

场景2 - 当我要评论value = 2incase 2:it时,说出局部变量值可能尚未初始化。

问题:

场景1:如果执行流程没有转到case 1:(当时为key = 2),那么它如何知道值变量asint的类型?

场景2:如果编译器知道值变量的类型为int,则它必须已访问到case 1:中的int value = 1;表达式(声明和初始化)。那么为什么sqawrk当我要发表评论value = 2incase 2:时,说当地变量值可能尚未初始化。


基本上,切换语句在范围方面是奇怪的。 Fromsection 6.3 of the JLS:

块(第14.4节)中局部变量声明的范围是声明出现的块的其余部分,从其自己的初始值设定项开始,并在本地变量声明语句中包含右侧的任何其他声明符。

在你的情况下,case 2在sameblockascase 1之后并出现在它之后,即使case 1将永远不会执行...所以局部变量在范围内并可用于写入,尽管你逻辑上从不"执行"声明。 (尽管初始化是,但声明并不是真正的"可执行"。)

如果你注释掉value = 2;分配,编译器仍然知道你指的是哪个变量,但是你不会通过任何为其赋值的执行路径,这就是你尝试读取时出现错误的原因任何其他未明确分配的局部变量。

我强烈建议你不要使用在其他情况下声明的局部变量 - 它会导致代码高度混乱,正如你所见。当我在switch语句中引入局部变量时(我很少尝试这样做 - 案例应该很短,理想情况)我通常更喜欢引入一个新的范围:

case 1: {
int value = 1;
...
break;
}
case 2: {
int value = 2;
...
break;
}

我相信这更清楚。


变量已声明(作为int),但未初始化(分配初始值)。想想这条线:

int value = 1;

如:

int value;
value = 1;

int valuepart在编译时告诉编译器你有一个名为value的变量,它是一个int。 value = 1part初始化它,但这发生在运行时,如果没有输入交换机的分支,则根本不会发生。


声明在编译时处理,不依赖于代码的执行流程。由于value是在switch块的本地范围内声明的,因此从声明的角度来看,它可以在该块中的任何位置使用。