Here is my code:
int x = 10;
switch(x) {
case 10:
System.out.println("10");
break;
case 5+5:
System.out.println("5+5");
break;
}
Here in this case, both cases are true, what will be executed? first case, or both?
It's invalid: 5+5 resolves to 10, and you cannot have two case clauses with the same constant.
As 5+5 is compiled as 10, your code has duplicate conditions, which is illegal in java switch statements.
From the specification :
No two of the case constant expressions associated with a switch
statement may have the same value.
So nobody can "explain the execution" : there is no execution.
You will get a "duplicate case" error.
According to your comment, this is the issue you observed.
The explaination is that 5+5 is evaluated to 10 at compile time by the compiler, which means that you have two case branches with the same value. This is not allowed (which one should the code take?)
Each case statement in a switch block must be unique. case 10 and case 5 + 5 are the same thing, and as such your code will not compile.
Related
I'm reluctant to use a switch, but I saw switch will be improved in Java 12
Java 12 added the switch expression as an experimental feature. A Java switch expression is a switch statement which can return a value.
The only use case I found (before Java 12) where switch may be useful is returning different values from a small closed set of cases, e.g.:
switch (input) {
case "A":
return "1";
case "B":
return "2";
default:
return "0";
}
Or in Java 12 example:
return
switch(digitInDecimal){
case 0 -> '0';
case 1 -> '1';
case 2 -> '2';
default -> '?';
But I found an old but high-ranked answer that says to avoid multiple return statements:
Assigning a value to a local variable and then returning that at the end is considered a good practice. Methods having multiple exits are harder to debug and can be difficult to read.
So I wonder, is that answer still relevant due to switch changes?
Must I wait for Java 12 where switch can be used without temporary variables and breaks?
Assigning a value to a local variable and then returning that at the end is considered a good practice.
I have no idea when it was considered a good practice. To me, switch is usually * an indicator that a design error was made. I would rather put my effort into thinking how to avoid a switch than into wondering how to return a value from a switch.
A few examples
Long list of if statements in Java
How to avoid switch-case statements in Java
Converting many 'if else' statements to a cleaner approach
Methods having multiple exits are harder to debug and can be difficult to read.
The same goes for a method that has a lot of breaks - that's what you are going to do if you choose the "local-variable approach".
In my opinion, none of these
// 1
switch (input) {
case "A":
return "1";
case "B":
return "2";
default:
return "0";
}
// 2
String varibleToReturn = null;
switch (input) {
case "A":
varibleToReturn = "1";
break;
case "B":
varibleToReturn = "2";
break;
default:
varibleToReturn = "0";
}
return varibleToReturn;
// 3
return switch(digitInDecimal) {
case 0 -> '0';
case 1 -> '1';
case 2 -> '2';
default -> '?';
}
makes a significant difference, or a slight improvement. Yes, Java-12's switch would give more conciseness and expressiveness, but the fundamental idea remains the same.
Must I wait for Java 12 where switch can be used without temporary variables and breaks?
What does it mean? :) No, the deadline is tomorrow, you have to work with what you've got at hand now.
*I am not underestimating the usefulness of switch. It may come in handy, for instance, when you programme at low-level, or you write an optimization.
I am just saying that in the real world, with Springs, and Hibernates, in a world of patterns, switch is obsolescent.
But I found an old but high-ranked answer that says to avoid multiple
return statements:
Assigning a value to a local variable and then returning that at the
end is considered a good practice. Methods having multiple exits are
harder to debug and can be difficult to read.
So I wonder, is that answer still relevant due to switch changes?
This is a common misconception, it originates form the phrase: "Single entry, single exit." (Page 24) All this originates from an other era, one that lead to structured programming languages and eventually to object oriented programming languages (like Java).
Don't worry about multiple return statements, there is nothing wrong with it.
I have a question. In a switch statement, is default tested for last even if it isn't last?
If so, in the following code snippet:
int i = 6;
int a=0, b=0, c=0;
switch (i)
{
case 1:
a++;
case 2:
default:
case 3:
b++;
case 6:
c++;
}
System.out.println(a + " " + b + " " + c);
After matching with case 6, and incrementing the value of c, since there is no break, will it go back to default?
I did try this code and it didn't seemly go to default and a fall-through did not occur. I just wanted to know?
switch is evaluated from matching case to either break or end of switch statement. If you pass 6 it will enter case for 6 and do only one increment. But if you enter 7 it will start from default and fall through to the end of switch doing two increments.
There is no additional testing of case labels beyond the initial testing at the beginning of the switch statement. Once i has been evaluated by the switch statement, control transfers to the case 6: label because that matches i. Statements are then executed in order until the end of the switch statement, or until a break statement is encountered. This means that only c is incremented.
A break statement will only end the execution of the entire switch statement; whether a break statement is present has no effect on retesting the switch expression, because retesting the switch expression will not occur either way.
If you want default to be the case label entered, then i must not match any case label at the start of the switch statement. If i is 99 at the start of the switch statement, then both b and c are incremented (fallthrough occurs).
There is no restriction on where in the order of case labels a default label appears, only that at most one default occurs in a switch statement.
Currently, all of your cases will fall through, as no case has a break; as well, your switch is conditionally based on i, so if you want to see each case, you need to change i.
Utilizing break; should not have any effect on where your cases reside in your switch state, this is also the "case" for default
Edit: As #Ivan mentioned, if fall through is intended, then the placement of your cases will matter
Here is a small confusion so kindly pardon my ignorance. Here is a code snippet.
public class SwitchTest {
public static void main(String[] args) {
int x = 2;
switch (x) {
case 1:
System.out.println("1");
break;
default:
System.out.println("helllo");
case 2:
System.out.println("Benjamin");
break;
}
}
}
Here, if value of x is 2, only Benjamin is printed. That's perfectly fine. Now lets suppose, i change value of x to 3, not matching any case, than its a fall through from default case. Ain't compiler needs to match every case for 3, by that time CASE 2 will be passed, than why it goes back to default and prints hello Benjamin. Can someone explain please?
Thanks,
You need to add a break; statement to break out of the switch block.
switch (x) {
case 1:
System.out.println("1");
break;
default:
System.out.println("helllo");
break; // <-- add this here
case 2:
System.out.println("Benjamin");
break;
}
Generally speaking, it is also better coding practice to have your default: case be the last case in the switch block.
In this case, the switch is following the pattern:
x==1? No, check next case
default? Not done yet, check other cases
x==2? No, check next case
//No more cases, so go back to default
default? Yes, do default logic
// no break statement in default, so it falls through to case 2: logic without checking the case
output case 2 logic
break
Notice how the block will jump over the default case, and save it until a later time unless we have exhausted all other possible cases.
It prints both strings because you do not have a break in your default case, so it continues into case 2, printing Benjamin. You could fix this by adding a break or moving case 2 above the default case.
'switch' case is other form of 'if-then-else', the default case is for the final else part. It is advisable to write default at the end of switch.
Default is checked as last. Thats why it feels like the compiler 'went' back.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
class switch1
{
public static void main(String args[])
{
int a = 10;
switch(a)
{
default: System.out.println("Default");
case -1: System.out.println("-1");
}
}
}
I understand that this program will execute both "default" and "case -1" statements as break is not specified after the matching condition (in this case after "default").
But what I fail to understand is
a) why is break needed in a switch statement?
b) why does it even execute the invalid matching conditions' statements (i.e executing "case -1")) if all it does is matching?
Sometimes you need multiple cases to execute the same function. For example, I am letting a user specify either mode 1 or mode 32 to represent 32-bit mode, and mode 2 or mode 64 for 64-bit mode.
switch (input) {
case 1:
case 32:
/* Do 32-bit related code */
break;
case 2:
case 64:
/* Do 64-bit related code */
break;
default:
System.out.println("Invalid input");
}
This is why breaks are important. They tell the switch statement when to stop executing code for a given scenario. Additionally, the default is generally used for when the switch does not match ANY case.
switch statements without breaks let you do things like this:
// Compute the most significant bit set in a number from 0 to 7
int topBit = -1;
switch(n) {
case 0:
topBit = 0;
break;
case 1:
topBit = 1;
break;
case 2:
case 3:
topBit = 2;
break;
case 4:
case 5:
case 6:
case 7:
topBit = 3;
break;
}
Essentially, it lets you create a set of labels, and have a condition at the top to let you jump to the initial label once. After that, the execution continues until a break, or reaching the end of the switch. This technique is old - it has been around since the assembly times, and by virtue of being included in C has made its way into Java and several other languages.
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 this documentation : http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
From the Java Language Specification section on the break statement:
A break statement transfers control out of an enclosing statement.
and...
a break statement ... always completes abruptly
a) It simply allows transfer of control out of the case statement.
b) The reason why it executes the conditions that aren't what you would expect to be matching is because there are particular conditions where falling through case statements would be considered valid (Taken from The Java Tutorials):
List<String> futureMonths = new ArrayList<String>();
int month = 8;
switch (month) {
case 1: futureMonths.add("January");
case 2: futureMonths.add("February");
case 3: futureMonths.add("March");
case 4: futureMonths.add("April");
case 5: futureMonths.add("May");
case 6: futureMonths.add("June");
case 7: futureMonths.add("July");
case 8: futureMonths.add("August");
case 9: futureMonths.add("September");
case 10: futureMonths.add("October");
case 11: futureMonths.add("November");
case 12: futureMonths.add("December");
break;
default: break;
}
for (String monthName : futureMonths) {
System.out.println(monthName);
}
Which outputs:
August
September
October
November
December
a) why does a switch statement relies heavily on a break statement to achieve its purpose ?
Because that's the way they defined it. It's copied from C. Pascal doesn't have fall-through, so it doesn't have break either. It also has case ranges, which Java lacks. Languages are allowed to be different. Or the same.
b) why does it even execute the invalid matching conditions' statements (i.e executing "case -1"))
Because that's the way they defined it, with fall-through if you don't put a break.
if all it does is matching ?
I don't understand the question. It doesn't do matching. It does an indexed jump to the relevant case, and falls through to the next statement if you don't put a break.
As for a., requiring the use of break allows shorthand notation where common code can be placed at the bottom block. This may make code more readable in some cases.
See "Switch statement fallthrough in C#?" for more information on fallthrough.
As for b., since it matches the default case, that line is executed. Because no break is present in that block, the next line is also executed regardless of a match.
Try
switch (a)
{
case 10: System.out.println("This is 10.");
case 9 : System.out.println("This is 9.");
break;
case 8 : System.out.println("This is 8.");
break;
default: System.out.println("Default");
}
Because there is no break in the matching case, the output is
This is 10.
This is 9.
Compare this with setting a to 11, 9, or 8.
If you add break to a loop, it cancels out of the loop. so for a switch statement it goes to the correct case and once it is there it carries out the code until the break where it will then exit the switch statemnt. If you removed the break it would carry on to the next case and until is sees a break. If there are no break; the code will crash.
So basically it separates different cases
In Switch case the 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.
The program SwitchDemoFallThrough shows statements in a switch block that fall through. The program displays the month corresponding to the integer month and the months that follow in the year:
public class SwitchDemoFallThrough {
public static void main(String[] args) {
java.util.ArrayList<String> futureMonths =
new java.util.ArrayList<String>();
int month = 8;
switch (month) {
case 1: futureMonths.add("January");
case 2: futureMonths.add("February");
case 3: futureMonths.add("March");
case 4: futureMonths.add("April");
case 5: futureMonths.add("May");
case 6: futureMonths.add("June");
case 7: futureMonths.add("July");
case 8: futureMonths.add("August");
case 9: futureMonths.add("September");
case 10: futureMonths.add("October");
case 11: futureMonths.add("November");
case 12: futureMonths.add("December");
break;
default: break;
}
if (futureMonths.isEmpty()) {
System.out.println("Invalid month number");
} else {
for (String monthName : futureMonths) {
System.out.println(monthName);
}
}
}
}
This is the output from the code:
August
September
October
November
December
Technically, the final break is not required because flow falls out of the switch statement. Using a break is recommended so that modifying the code is easier and less error prone. The default section handles all values that are not explicitly handled by one of the case sections.
Look Here for complete information about switch
a) Why fall-through / required break in switch?
The fall-through behavior is useful in some cases, but the problem is that it's extra work in the common case. Therefore it's reasonable to expect that the "break" keyword would not be required in a more modern language
So why is it there? To match the behavior of C++ (dominant language at the time Java was designed), which again matches the behavior of C (dominant language at the time C++ was designed). As for C, it (and B and BCPL, its predecessors) usually looks the way it does to make it easier to build an efficient compiler. Basically the way the switch statement works is the natural way to implement it in assembler.
b) The way it behaves follows logically from the decision to use fall-through.
I am relatively new to java. In a switch statement, do you have to put a break statement after each case?
No, you don't have to. If you omit the break statement, however, all of the remaining statements inside the switch block are executed, regardless of the case value they are being tested with.
This can produce undesired results sometimes, as in the following code:
switch (grade) {
case 'A':
System.out.println("You got an A!");
//Notice the lack of a 'break' statement
case 'B':
System.out.println("You got a B!");
case 'C':
System.out.println("You got a C.");
case 'D':
System.out.println("You got a D.");
default:
System.out.println("You failed. :(");
}
If you set the grade variable to 'A', this would be your result:
You got an A!
You got a B.
You got a C.
You got a D.
You failed. :(
You don't have to break after each case, but if you don't they will flow into each other. Sometimes you want to bundle multiple cases together by leaving out the breaks.
It is better you do. Otherwise the next statements will be executed too.
switch(someNumber) {
case thisCaseMatches:
doThat();
case thisCaseDoesNotMatch:
shouldntExecuteYetItWillBeExecuted();
default:
alsoWillbeExecuted();
}
You do if you are not exiting the switch statement with a return or other action.
Semantically yes. Otherwise all case statements after the first matching one would run.
It's a good practice to put break after each statement.
You're not forced.
But if you don't put breaks tatement you've cascade switch statement, namely more condition could be matched, and sometimes this can lead to logical errors.
However there are people which think that cascade statements can optimize the code, helping to write less code.