在 Java 开关中声明和初始化变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10810768/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Declaring and initializing variables within Java switches
提问by namalfernandolk
I have a crazy question about Java switches.
我有一个关于 Java 开关的疯狂问题。
int key = 2;
switch (key) {
case 1:
int value = 1;
break;
case 2:
value = 2;
System.out.println(value);
break;
default:
break;
}
Scenario 1 - When the key
is two it successfully print the value as 2.
Scenario 2 - When I'm going to comment value = 2
in case 2:
it squawks saying the The local variable value may not have been initialized.
场景 1 - 当它key
是 2 时,它成功地将值打印为 2。
场景 2 - 当我要在其中发表评论时value = 2
,case 2:
会抱怨说The local variable value may not have been initialized。
Questions :
Scenario 1 : If the execution flow doesn't go to case 1:
(when the key = 2
), then how does it know the type of the value variable as int
?
Scenario 2 : If the compiler knows the type of the value variable as int
, then it must have accessed to the int value = 1;
expression in case 1:
.(Declaration and Initialization). Then why does it sqawrk When I'm going to comment value = 2
in case 2:
, saying the The local variable value may not have been initialized.
问题:
场景 1:如果执行流程没有转到case 1:
(当key = 2
),那么它如何知道 value 变量的类型为int
?
场景 2:如果编译器知道 value 变量的类型为int
,那么它必须访问.(Declaration and Initialization) 中的int value = 1;
表达式case 1:
。那么为什么它sqawrk当我要评论value = 2
中case 2:
,称局部变量的值可能没有被初始化。
回答by Jon Skeet
Switch statements are odd in terms of scoping, basically. From section 6.3 of the JLS:
Switch 语句在范围方面很奇怪,基本上。从JLS 第 6.3 节:
The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration appears, starting with its own initializer and including any further declarators to the right in the local variable declaration statement.
块中局部变量声明的范围(第 14.4 节)是该声明出现的块的其余部分,从它自己的初始化程序开始,并包括局部变量声明语句右侧的任何其他声明符。
In your case, case 2
is in the same blockas case 1
and appears after it, even though case 1
will never execute... so the local variable is in scope and available for writingdespite you logically never "executing" the declaration. (A declaration isn't really "executable" although initialization is.)
在您的情况下,与case 2
它在同一个块中case 1
并出现在它之后,即使case 1
永远不会执行......所以局部变量在范围内并且可以写入,尽管您在逻辑上从不“执行”声明。(虽然初始化是,但声明并不是真正的“可执行”。)
If you comment out the value = 2;
assignment, the compiler still knows which variable you're referring to, but you won't have gone through any execution path which assigns it a value, which is why you get an error as you would when you try to read any other not-definitely-assigned local variable.
如果您将value = 2;
赋值注释掉,编译器仍然知道您指的是哪个变量,但您不会经过任何为其分配值的执行路径,这就是为什么您会像尝试那样得到错误读取任何其他未确定分配的局部变量。
I would strongly recommend you notto use local variables declared in other cases - it leads to highly confusing code, as you've seen. When I introduce local variables in switch statements (which I try to do rarely - cases should be very short, ideally) I usually prefer to introduce a new scope:
我强烈建议您不要使用在其他情况下声明的局部变量 - 正如您所见,这会导致代码高度混乱。当我在 switch 语句中引入局部变量时(我很少尝试这样做 - 理想情况下,情况应该非常短)我通常更喜欢引入一个新的作用域:
case 1: {
int value = 1;
...
break;
}
case 2: {
int value = 2;
...
break;
}
I believe this is clearer.
我相信这更清楚。
回答by Paul
The variable has been declared (as an int), but not initialized (assigned an initial value). Think of the line:
变量已声明(作为 int),但未初始化(分配了初始值)。想想这条线:
int value = 1;
As:
作为:
int value;
value = 1;
The int value
part tells the compiler at compile time that you have a variable called value which is an int. The value = 1
part initializes it, but that happens at run-time, and doesn't happen at all if that branch of the switch isn't entered.
该int value
部分在编译时告诉编译器您有一个名为 value 的变量,它是一个 int。该value = 1
部分对其进行初始化,但这发生在运行时,如果未进入该开关的该分支,则根本不会发生。
回答by Garbage
Declarations are processed at compile time and do not depend on the execution flow of your code. Since
value
is declared within the local scope of the switch block, it is useable anywhere in that block from the point of its declaration.
声明在编译时处理,不依赖于代码的执行流程。因为
value
是在 switch 块的局部范围内声明的,所以从它的声明点开始,它可以在该块的任何地方使用。
回答by Naman
With the integration of JEP 325: Switch Expressions (Preview)in JDK-12 early access builds. There are certain changes that could be seen from Jon's answer-
通过在 JDK-12 早期访问版本中集成JEP 325:切换表达式(预览版)。从乔恩的回答中可以看出某些变化 -
Local Variable Scope- The local variables in the switch cases can now be local to the case itself instead of the entire switch block. An example (similar to what Jon had attempted syntactically as well) considering the
Day
enum class for further explanation :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); } }
Switch Expressions- If the intent is to assign a value to a variable and then make use of it, once can make use of the switch expressions. e.g.
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' }
局部变量作用域- switch case 中的局部变量现在可以是 case 本身的局部变量,而不是整个 switch 块。考虑
Day
枚举类以进行进一步解释的示例(类似于 Jon 在语法上尝试的内容):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); } }
Switch 表达式- 如果意图是为变量赋值然后使用它,则一次可以使用 switch 表达式。例如
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' }
回答by Java jansen
This Explanation might help.
这个解释可能会有所帮助。
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
}
}
回答by Pavel Molchanov
Java spec:
Java规范:
https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.11
https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.11
The case of abrupt completion because of a break with a label is handled by the general rule for labeled statements (§14.7).
由于带标签的中断而突然完成的情况由带标签语句的一般规则(第 14.7 节)处理。
https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.7
https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.7
Labeled statements:
标记语句:
LabeledStatement: Identifier : Statement
LabeledStatementNoShortIf: Identifier : StatementNoShortIf
Unlike C and C++, the Java programming language has no goto statement; identifier statement labels are used with break (§14.15) or continue (§14.16) statements appearing anywhere within the labeled statement.
The scope of a label of a labeled statement is the immediately contained Statement.
LabeledStatement:标识符:声明
LabeledStatementNoShortIf:标识符:StatementNoShortIf
与 C 和 C++ 不同,Java 编程语言没有 goto 语句;标识符语句标签与出现在标记语句中任何位置的 break(第 14.15 节)或 continue(第 14.16 节)语句一起使用。
带标签语句的标签范围是直接包含的语句。
In other words, case 1, case 2 are labels within the switch statement. break and continue statements can be applied to labels.
换句话说,case 1、case 2 是 switch 语句中的标签。break 和 continue 语句可以应用于标签。
Because labels share the scope of the statement, all variables defined within labels share the scope of the switch statement.
因为标签共享语句的范围,所以标签中定义的所有变量共享 switch 语句的范围。