我对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 -当我要评论value = 2
的case 2:
它叫声称局部变量的值可能没有被初始化 。
问题:
方案1:如果执行流不进入case 1:
当key = 2
),那么它是如何知道变量的值作为类型int
?
情形2:如果编译器知道变量的值作为类型int
,那么它必须已经访问到int value = 1;
在表达case 1:
声明和初始化)。 那么,为什么它sqawrk当我要评论value = 2
的case 2:
说的局部变量的值可能没有被初始化 。
开关语句是在范围界定方面奇怪,基本上是这样。 从JLS的第6.3 :
在一个块中(§14.4)的局部变量声明的范围是在其中出现的声明,开始与它自己的初始化,并且包括任何进一步说明符在局部变量声明声明权利的块的其余部分。
在你的情况, case 2
是在同一个块中case 1
和后它的出现,即使case 1
永远不会执行......所以,局部变量是在范围和可写 ,尽管你从来没有逻辑“执行”的宣言。 (A声明是不是真的“可执行”尽管初始化。)
如果您注释掉value = 2;
分配时,编译器仍然知道你指的是哪个变量,但你不会有通过给它分配一个值的任何执行路径,这就是为什么你得到一个错误,你会当您尝试读取任何其他不可─不见了绝对分配的局部变量。
我强烈建议你不要使用在其他情况下,声明的局部变量-它会导致非常混乱的代码,如您所见。 当我介绍switch语句中的局部变量(我尝试很少这样做 - 的情况下应该是很短的,理想情况下)我通常喜欢引入新的范围:
case 1: {
int value = 1;
...
break;
}
case 2: {
int value = 2;
...
break;
}
我相信这是更清晰。
变量已被宣布(作为int),但尚未初始化(分配一个初始值)。 思而行的:
int value = 1;
如:
int value;
value = 1;
该int value
部分告诉在你有一个变量,名为值是一个int编译时,编译器。 该value = 1
一部分初始化,但这种情况发生在运行时,在所有的,如果没有输入开关的一个分支不会发生。
从http://www.coderanch.com/t/447381/java-programmer-SCJP/certification/variable-initialization-within-case-block
声明是在编译时处理,不依赖于你的代码的执行流程。 由于value
是开关块的局部范围内声明的,它是在该块可用在任何地方进行了声明的地步。
随着整合JEP 325:开关表达式(预览)在JDK-12早期访问版本。 有可能从可以看出某些变化乔恩的答案 -
局部变量范围 -在切换的情况下的局部变量现在可以是本地的案件本身,而不是整个交换机模块 。 一个例子(类似于乔恩是语法试图为好)考虑到Day
进一步解释枚举类:
public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY } // some another method implementation Day day = Day.valueOf(scanner.next()); switch (day) { case MONDAY,TUESDAY -> { var temp = "mon-tue"; System.out.println(temp); } case WEDNESDAY,THURSDAY -> { var temp = Date.from(Instant.now()); // same variable name 'temp' System.out.println(temp); } default ->{ var temp = 0.04; // different types as well (not mandatory ofcourse) System.out.println(temp); } }
开关表达式 -如果意图是一个值赋给变量,然后利用它,一旦可以利用开关表达式。 例如
private static void useSwitchExpression() { int key = 2; int value = switch (key) { case 1 -> 1; case 2 -> 2; default -> {break 0;} }; System.out.println("value = " + value); // prints 'value = 2' }
这说明可能有帮助。
int id=1;
switch(id){
default:
boolean b= false; // all switch scope going down, because there is no scope tag
case 1:
b = false;
case 2:{
//String b= "test"; you can't declare scope here. because it's in the scope @top
b=true; // b is still accessible
}
case 3:{
boolean c= true; // case c scope only
b=true; // case 3 scope is whole switch
}
case 4:{
boolean c= false; // case 4 scope only
}
}