简体   繁体   English

Java7和Java8中的switch-case语句中的行为不一致

[英]Not coherent behaviour in switch-case statement in Java7 and Java8

I'm preparing for Java7 Oracle certificate and I'm wondering why Java handles switch-case in such a weird way: 我正在准备Java7 Oracle证书,并且想知道为什么Java以这种奇怪的方式处理切换情况:

    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;
    }
}

That's obvious why case 0 and case 3 inform about unknown symbol or uninitialized variable, but I can't imagine why case 2 is working properly? 这很明显为什么情况0和情况3会通知未知符号或未初始化的变量,但是我无法想象为什么情况2可以正常工作? How compiler knows about the type of b if it's assigned in case 1? 如果b在情况1中被分配,编译器如何得知b的类型? For me that's not coherent. 对我而言,这并不连贯。

UPDATE1: Actually what is even more weird is that in case 3 I noticed compile time error (Linux64, Java7 and Java8), but some of my colleagues do not. UPDATE1:实际上,更奇怪的是,在情况3中,我注意到编译时错误(Linux64,Java7和Java8),但是我的一些同事却没有。

I prepared very simple maven project: https://github.com/gonciarz/switch-test 我准备了一个非常简单的Maven项目: https : //github.com/gonciarz/switch-test

UPDATE2: It seems that for everyone case3 does not compile. UPDATE2:似乎对每个案例case3都不编译。 Thank you guys for your clarifications. 谢谢你们的澄清。

You are mixing up declaration and assignment. 您正在混合声明和赋值。 In your code 在你的代码中

case 1:
    boolean b=false;
    break;
case 2:
    b = true; // how case knows about existence of variable b?
    break;

the variable b is declared and assigned in case 1: . case 1:声明分配变量b The scope of the declaration is the rest of the switch statement's block, ie up to the } . 声明的范围是switch语句块的其余部分,即直到}为止。

It's the same as if you had written: 就像您写过的一样:

case 1:
    boolean b;// declaration
    b=false;  // assignment
    break;

The assignment has no effect for the code flow for the case 2: label. 分配case 2:标签的代码流无效。 If a jump to the case 2 label happens, the variable is declared but not assigned as an assignment can be skipped but not a declaration. 如果发生跳转到case 2标签,则声明变量但未分配该变量,因为可以跳过一个赋值但不能声明。

So the behavior is consistent with your third label: 因此,该行为与您的第三个标签一致:

case 3:
    System.out.println(b); // var b might not have been initialized
    break;

Here, the variable b is declared , but not assigned . 在此, 声明了变量b ,但未赋值 That's what the error message tells you: it doesn't say that b was undeclared but that it “might not have been initialized”, which includes the possibility that you know for sure, that it has not been initialized at this point. 这就是错误消息告诉您的内容:它不是说未声明b ,而是“可能尚未初始化”,其中包括您肯定知道它尚未被初始化的可能性。

The type of b is the declared type and not dependent on any assignment. b类型声明的类型,并且不依赖于任何赋值。


As a side note, there are differences between switch and if . 作为附带说明, switchif之间有区别。 Had you written 你写了吗

final int a = 2;
boolean b;
if(a == 2) b=false;
System.out.println(b);

the constant nature of a caused the compiler to detect that b will be assigned to false and no error was generated. 的恒定性质a引起编译器来检测b将被分配到false且没有产生错误。 That works for if but not for switch . 这适用于if但不适用于switch

Your scope here is the entire switch clause, not the separate cases. 您的范围是整个switch子句,而不是单独的情况。 Scopes are defined by the { and } . 范围由{}定义。

When you declare your variable with boolean b = false it is accessible in the rest of the scope, ie the rest of the switch clause. 当使用boolean b = false声明变量时,可以在范围的其余部分(即switch子句的其余部分)中访问它。

You do not get an error in case 3 as you mention in your question. 您在问题中提到的情况3不会出错。

Edit: You do get an error in case 3 but it seems Eclipse is sloppy in detecting it. 编辑:在情况3中确实会出现错误,但是Eclipse在检测它时似乎很草率。 I was confusing field declarations which get a default value for primitives with local variables which do not. 我将字段声明与原始变量的默认值与没有的局部变量混淆了。

The rules says this: 规则说:

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节)是该声明在其中出现的其余部分,从其自身的初始化程序开始,并在该局部变量声明语句的右侧包括其他任何声明符。

and this 和这个

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块的局部范围内声明的,因此从声明的位置开始,该值可在该块中的任何位置使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM