Reputation: 387
I'm preparing for Java7 Oracle certificate and I'm wondering why Java handles switch-case in such a weird way:
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? How compiler knows about the type of b
if it's assigned in case 1? 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.
I prepared very simple maven project: https://github.com/gonciarz/switch-test
UPDATE2: It seems that for everyone case3 does not compile. Thank you guys for your clarifications.
Upvotes: 1
Views: 134
Reputation: 13696
Your scope here is the entire switch clause, not the separate cases. Scopes are defined by the {
and }
.
When you declare your variable with boolean b = false
it is accessible in the rest of the scope, i.e. the rest of the switch clause.
You do not get an error in case 3 as you mention in your question.
Edit: You do get an error in case 3 but it seems Eclipse is sloppy in detecting it. I was confusing field declarations which get a default value for primitives with local variables which do not.
Upvotes: 1
Reputation: 298409
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:
. The scope of the declaration is the rest of the switch
statement’s block, i.e. up to the }
.
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. 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.
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. 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.
The type of b
is the declared type and not dependent on any assignment.
As a side note, there are differences between switch
and if
. 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. That works for if
but not for switch
.
Upvotes: 4
Reputation: 3972
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.
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.
Upvotes: 1