Why isn't the scope of a switch statement in Java limited? - java

Why, in Java, is a variable's scope confined to a switch block as opposed to a case block. For example,
// Scope limited to a switch block
switch (number) {
case 1:
String result = "...";
break;
case 2:
result = "...";
break;
In the above example, result needs only to be declared once. If you declare it twice then you receive a Duplicate local variable message.
My question is: how does the program know you've declared result if number = 2?
(It won't fall into case 1 and won't declare the variable... or will it?)
EDIT:
I might be confusing everyone. I understand how I can limit the scope of a variable but my question is: how does Java know that result has been declared if it doesn't fall into the case?

EDIT: Java uses lexical scoping (also called static scoping), so the scope of the variables are determined during compile time, and have nothing to do with the actual evaluation.
Java is block scoped, so it's scope will respect the {} in the example above.
See 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.

You can limit the scope to case blocks by adding curly brackets like this:
// Scope limited to a switch block
switch (number) {
case 1:{
String result = "...";
break;
}
case 2:{
String result = "...";
break;
}

In the grandfather language Fortran, there is a computed GOTO statement
GOTO expr
...
1 ...
...
2 ...
...
based on the value of expr, the code jumps to 1, 2 etc.
C's (and Java's) switch statement is basically a computed GOTO in disguise. We have a continuous piece of code with some labels, and we jump to one of the label. If there's no break we'll execute the rest of the block.
This rather low level control mechanism is contrary to the intuitions of today's programmers; we would think that the switch statement selects one clause and executes that clause, much like an if-elseif-elseif-...-else statement.
Java inherited C's switch semantics since they didn't want to deviate from C too much. Newer languages are unlikely to continue the mistake.

Java uses block scoping, select cases aren't blocks (they are more like labels). This would work though:
switch (key) {
case 1: {
String result = "1";
return result ;
}
case 2: {
String result = "2";
return result ;
}
}

What do you mean how? In order to understand the answer you need to learn how compilers work.
Think of the switch as a large block with multiple "goto" statements at the end of each switch statement.
I'm not sure how java unroll switch statements but one easy and simple way to do it is this (pseudo byte-code):
if (number == 1) goto label1;
if (number == 2) goto label2;
goto labelEnd;
label1:
String result = "...";
goto labelEnd;
label2:
result = "...";
goto labelEnd;
labelEnd:
<some code>

The reason a variable scope is confined to a switch block as opposed to a case block is java allows for fall through from one case block to the next i.e.
switch (number) {
case 1:
.... some code ...
case 2:
.... some more code ...
in this case case if number is 1, both case 1 & case 2 are executed. The break acts like a goto end of select, it does not ever end scope. The variable scope has to be at select level.
As others have stated, use a block to restrict scope i.e.
switch (number) {
case 1:{
String result = "...";
break;
}
case 2:{
String result = "...";
break;
}

Because there isn't a 'case block'.
Everything inside the switch statement is in the same block. You can't declare the same variable twice in the same block.
If you want a 'case block' you have to write the { and } yourself.

Related

Can I use switch case in Java instead of IF, if I need several cases to be evaluated

I have a primitive question but I can't actually recall the answer.
What if I use Switch Cases instead of IF\ELSE IF. Will all cases get evaluated or break will break out of the whole switch cases and return the first satisfied condition only.
In other words, what if I want to check if someone has a car, bike and plane. And in my particular case someone has all of them would switch return all three as true or it will return the first case only and ignore the rest because of the break?
Sorry for inconvenience.
Thank you
From the Official Java Tutorials :
Each break statement terminates the enclosing switch statement.
In your particular case, if someone has a car, bike or a plane, you should construct more complex if\else statement.
But if you still prefer to use switch, you can do the following:
switch (possession)
{
case CAR:
case BIKE:
case PLANE:
doSomething();
break;
}
It will break out at the first matching. the best thing to do in your case is using logical operators in if statements.
if (hasCar && hasBike && hasPlane)
{
...
}
The break terminates the switch-statement.
Besides, switch evaluates a single variable, your case sounds a bit more complex to me.
certainly break will break the switch-case flow after encountering first break statementif no break is found then it will start the execution of all statement starting from first matching case,you can implement the logic inside case.and one thing more switch case is little bit faster than if-else
please see Why switch is faster than if
With switch the first case it finds a match runs and then all the following cases regardless of matching or not, provided you don't use break. By using break,only the actual match case runs and it is almost always only one. Therefore I do not regard in your problem using switch as a good approach, since you can handle it better with if-else.
Perhaps you would need to rewrite a new style of Data Structure to confirm this. The easyest way that I think is with a Boolean Array (bool[]);
Continuing with your example if you has the
Owner Class
, with
bool bike, bool car, bool motocycle... properties, witch you can write a
public bool[] ownArray()
function, that can be evaluated.
I hope this helps.
myEnum = 3;
...
switch (myEnum) {
case 1: System.out.println("This will not print"); break;
case 2: System.out.println("This will not print"); break;
case 3: System.out.println("This will print!"); //no break!
case 4: System.out.println("So will this, because there wasn't a break"); break;
case 5: System.out.println("But this won't, there was a break");
}
Switch-case in java could evaluate one case at a time. The moment it gets into one of the case, it would keep on executing the next statements (no matter, if those statement were part of other case ); until it hit a break;
In nutshell, A switch statement gives you the option to test for a range of values for your variables. They can be used instead of long, complex if … else if statements. The structure of the switch statement is this:
switch ( variable_to_test ) {
case value1: code_here1;
break;
case value2: code_here2;
case value3: code_here3;
break;
default:
values_not_caught_above;
}
In the above example if value2 is satifies, it will execute code_here2 and code_here3 as well (because there is no break statement)
Sadly, you can't test for a range of values after case, just the one value. So you can't do this:
case (user <= 18):

Understanding switch behaviour

Consider the following code
int x = 1
switch(x) {
case 1:
System.out.println("1");
case 2:
System.out.println("2");
default:
System.out.println("no value found");
}
it prints
1
2
no value found
as expected because there is no break in each case statement
my doubt is that how execution goes to each case statement if there is no break in first one
because x is not equal 2 then also its execute case 2 block
but i understood default one because without break program continue its execution and execute the default statement
This is a remnant of the C programming language. In C switch is little more than a little syntactic sugar over a goto depending on the expression value and thus execution simply jumps to the appropriate case and continues from there. The labels in between are exactly that: labels. They are jump targets but don't affect control flow otherwise and from the compiler's point of view there is nothing in a label that merits a jump elsewhere (except there is INTERCAL's COMEFROM somewhere). So you have to put an explicit break after every case where you don't want to fall through to other options.
Java more or less inherited those semantics while eschewing some of the crazier C idioms.
C# on the other hand goes a bit further by disallowing fall-through entirely on non-empty case labels.
In my opinion though, this was a bit of a design error. Fall-through by default may be much easier to implement in the compiler (because you don't have to add a goto to the end of the switch and it aligns very nicely with how things actually work underneath), but in my experience there are vastly more programming errors by accidentally using fall-through than by accidentally not using it.
The most severe design error in my eyes is including the switch statement with all its weirdness in modern languages.
For reasons that are inherited from C++, execution naturally proceeds until the end of switch or a break. There is no test against cases as they are encountered.
switch is fall through. You need to add break before each next case unless you want that.
switch (x) {
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
default:
System.out.println("no value found");
}
It's to do with how it's compiled and optimization.
It's why a switch is preferable to a bunch of chained if statements.
From java doc:
The break statements are necessary because without them, statements in
switch blocks fall through: All statements after the matching case
label are executed in sequence, regardless of the expression of
subsequent case labels, until a break statement is encountered
The switch statement is not like an if-then-else statement. switch statement has multiple execution path.
The Documentation states:
Control flow continues with the first statement following the switch
block. The break statements are necessary because without them,
statements in switch blocks fall through: All statements after the
matching case label are executed in sequence, regardless of the
expression of subsequent case labels, until a break statement is
encountered.
The switch statement is an abstraction of a branch table, and a branch table also has an implicit fall-through and requires an additional jump instruction to avoid it. Read this SO answer as well.
As per JLS 14.11:
The body of a switch statement is known as a switch block.
If one of the case constants is equal to the value of the expression, then we say that the case matches, and all statements after the matching case label in the switch block, if any, are executed in sequence.
If all these statements complete normally, or if there are no statements after the matching case label, then the entire switch statement completes normally.
It's correct behaviour. "default" doesn't mean all possible answers. It means all answers without these written in cases.
int x=1
switch(x)
{
default:
System.out.println("no value found");
case 1:
System.out.println("1");
case 2:
System.out.println("2");
}
will print
1
2
won't print
no value found
1
2
when using breaks; statements and default value there is called only one "branch" for each value
Each break statement terminates the enclosing switch statement. All statements after the matching case label are executed in sequence, regardless of the expression of subsequent case labels, until a break statement is encountered.
You can use if-then-else just, the overhead of testing is increases..., which is avoided in switch-case, but break is necessary for proper execution...

Switch case logical expression statement in Java - versus JS or PHP

in JavaScript and also I've seen it in PHP : You can use a logical expression inside you cases :
For Example :
switch(true){
case (d<10):
document.write("Less than 10");
break;
case (d==10):
document.write("Equal to 10");
break;
case (d>10):
document.write("Greater than 10");
break;
default:
document.write("Some dumb error. Probably not a number.");
}
I was wondering if we can do this in Java ... say I needed a to compare a very large range.
case 1 :
case 2 :
...
case 5000:
case 5001:
default:
It would be tedious to do. I could wrap my cases inside if statements but i was wondering it could be done like in JavaScript or PHP.
It is nice to have, but you cannot. Quoting JLS:
The body of a switch statement is known as a switch block.
Any statement immediately contained by the switch block may be labeled with one or more switch labels, which are case or default labels.
These labels are said to be associated with the switch statement, as are the values of the constant expressions (§15.28) or enum constants (§8.9.1) in the case labels.
These labels have to be constant expressions or enum constants.
No You cannot do that using switch in java. You have to use if-else to accomplish this.
See this link for more details.

Using Case Statements

I'm using int[] arrays as a reference. I wondering if my use of case statements is sound or if it will cause errors down the line.
This is my code:
int switcheroo = intarray[0];
int foo = intarray[1];
boolean size = false;
boolean biggersize = false;
switch (switcheroo) {
case 0:
switch (foo) {
case 1:
doSomething(switcheroo); //change switcheroo somehow.
break;
case 2:
doSomethingElse(switcheroo); //change switcheroo differently.
break;
}
case 1:
size = true;
break;
case 2:
biggersize = true;
break;
default:
break;
}
Unless it's a coincidence, this is working to ripple the changes from the nested case statement into the other cases, as I want.
My questions are:
Will this nesting causes trouble further down the line?
Is the lack of a break; after a case bad practice?
Thanks.
Edit: The methods which change switcheroo in the middle of the switch statements were put there for responses to that. I will not be doing this is my program.
Nesting won't cause trouble down the line exactly, but it can be confusing to read. Adding comments and/or other documentation will really help future coders (and yourself in a week!) understand this by looking at it.
The lack of a break isn't a bad practice by itself, but it is something that -most- case statements have, so I would add a comment at the end like // no break, allow fall-through.
So both cases boil down to good documentation.
These points are perpendicular to the fact that I don't think this code does what you think it will do.
The case clause is not reevalauted every time you come across one - they're just points to jump to for the switch. So in your example, you will always end up in case 1 if you start at case 0 - you'll never end up at case 2 from case 0.
If I were to restructure this, here's what I would do. Instead of using int, I would use enum:
enum Foo { GOOD_FOO, BAD_FOO }
enum Switcharoo { BAR, BAZ, BAQ, ESCAPE }
enum Size { NONE, REGULAR, BIGGER }
Foo foo = ... // assigned somewhere
Switcharoo roo = ... // assigned somewhere
Size size = NONE;
// use a while loop to reevalulate roo with each pass
while(roo != Switcharoo.ESCAPE) {
switch(roo){
case BAR:
switch(foo) {
case GOOD_FOO: foo = doSomething(foo); break;
case BAD_FOO: foo = doSomethingElse(foo); break;
}
break;
case BAZ:
roo = Switcharoo.ESCAPE;
size = Size.REGULAR;
break;
case BAQ:
roo = Switcharoo.ESCAPE;
size = Size.BIGGER;
break;
}
}
RE: Is the lack of a break; after a case bad practice?
If you don't include a break after each case statement the flow will continue trough the next statements, so the code for more than one option will be executed.
From the Java Tutorial:
Another point of interest is the break statement. Each break statement
terminates the enclosing switch statement. Control flow continues with
the first statement following the switch block. The break statements
are necessary because without them, statements in switch blocks fall
through: All statements after the matching case label are executed in
sequence, regardless of the expression of subsequent case labels,
until a break statement is encountered.
Check http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html to learn more details about switch statements.
In case foo is neither 1 nor 2, is switcheroo supposed to continue to case 1? If yes, your code is correct. If not, you need to add a break before case 1
switch operator is a kind of conditional if operator. And a bunch of if operators may report that you need to involve object polymorphism in your code instead of making sequental if-switch operators.
Consider re-arranging your data to classes/objects and process them using polymorphism approach. It will make your code more reliable, more manageable and just more beautiful.
Im not sure if i understood your first question, can you give me some more information (concrete maybe)?
Concerning the second question, there's nothing wrong about not having a break statement after a case, as long as you know that the code will continue to execute till it finds a break statement.
well..It seems the only thing you lack here is readability. Do this type of nesting only if you are forces to do.
Is the lack of a break; after a case bad practice?
not bad rather it is a good practice to avoid unsual behaviour. Your code will continue executing to your last case in absensce of this Break.
Add break in your first outer case too.
I'd recommend avoiding nesting and fall-through in combination. At least personally, I tend to expect that every case ends with a break, so I'd use fallthrough only in cases where it's very easy to spot, and leads to clearer code than an if..else, such as:
switch (foo) {
case 0:
case 1:
doSomething();
break;
case 2:
doSomethingElse();
break;
default:
break;
}
That is, with either empty or very simple (one statement) case bodies. In your case, refactoring the body of the first case into a method would probably work:
void changeSwitcheroo(int foo, int switcheroo) {
switch (foo) {
case 1:
doSomething(switcheroo); //change switcheroo somehow.
break;
case 2:
doSomethingElse(switcheroo); //change switcheroo differently.
break;
}
}
// ...
int switcheroo = intarray[0];
int foo = intarray[1];
switch (switcheroo) {
case 0:
changeSwitcheroo(foo, switcheroo);
case 1:
size = true;
break;
case 2:
biggersize = true;
break;
default:
break;
}
(This is mostly arguing readability and style. The meaning of the switch will still be "if switcheroo is 1, jump into the middle of case 0.)
If there are only 2 alternatives, prefer an if/else. Fewer lines of code and no break issues.
Will this nesting causes trouble further down the line?
A problem is that such switch nesting is hard to read: I had to look at the code twice before I noticed that you were using a nested switch. This can be a maintenance issue, but that isn't a reason not to use a nested switch, just use this sparingly, adjust your indentation to clarify what's going on, and comment on the usage.
Is the lack of a break; after a case bad practice?
Falling through by omitting the break can also lead to maintenance/debugging issues, but I don't consider it bad practice. It is, after all, intrinsic in the design of the switch statement. A fall through comment is always welcome so that the next guy - or you, revisiting your code months later - knows that the fall-through is intentional.

Appropriate use of Multi-level Break in Java

I was recently coding a small java program (as design for an 8086 Assembler program) and I wound up in an interesting position -- I needed to exit out of a while loop from an inner switch-statement, something like this (pseudocode, obviously):
:MyLoop
While(foo)
switch (bar)
case '1': print '1'; break
case '0': print '0'; break
case ';': end while loop;
It seemed like the perfect place for a goto statement because a single "break" would only exit the switch statement,(especially considering that I was designing for assembly) but Java has no gotos!
I found instead that Java has something called a multi-level break, so by using "break MyLoop", the program would break out of both the switch case and the while loop. '
My question then -- is this an appropriate use of a multi-level break? If, for some reason, I wanted to keep the switch (instead of, say, nested else ifs) statement, is there an alternative way to mimic a multi-level break via "break" or "continue" alone?
Personally I would usually regard this as a hint to refactor the loop into its own method - then you can return from the whole method instead of just breaking out of the loop.
I personally find that clearer in most cases - but otherwise, this is exactly the kind of thing that labeled breaks are there for. It's generally cleaner (IMO) than having a separate boolean variable indicating whether or not to continue the loop.
is this an appropriate use of a multi-level break?
Yes.
is there an alternative way to mimic a multi-level break via "break" or "continue" alone?
You could set a boolean flag and then break at each level.
Jon Skeet's answer in code:
public void doSomething() {
while(foo) {
switch (bar) {
case '1': print '1'; break;
case '0': print '0'; break;
case ';': return; //Effectively exits the loop
}
}
}

Categories