Why doesn\'t the compiler automatically put break statements after each code block in the switch? Is it for historical reasons? When would you want multiple code blocks to e
The break
after switch case
s is used to avoid the fallthrough in the switch statements. Though interestingly this now can be achieved through the newly formed switch labels as implemented via JEP-325.
With these changes, the break
with every switch case
can be avoided as demonstrated further :-
public class SwitchExpressionsNoFallThrough {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int value = scanner.nextInt();
/*
* Before JEP-325
*/
switch (value) {
case 1:
System.out.println("one");
case 2:
System.out.println("two");
default:
System.out.println("many");
}
/*
* After JEP-325
*/
switch (value) {
case 1 ->System.out.println("one");
case 2 ->System.out.println("two");
default ->System.out.println("many");
}
}
}
On executing the above code with JDK-12, the comparative output could be seen as
//input
1
// output from the implementation before JEP-325
one
two
many
// output from the implementation after JEP-325
one
and
//input
2
// output from the implementation before JEP-325
two
many
// output from the implementation after JEP-325
two
and of course the thing unchanged
// input
3
many // default case match
many // branches to 'default' as well
Historically, it's because the case
was essentially defining a label
, also known as the target point of a goto
call. The switch statement and its associated cases really just represent a multiway branch with multiple potential entry points into a stream of code.
All that said, it has been noted a nearly infinite number of times that break
is almost always the default behavior that you'd rather have at the end of every case.
Why doesn't the compiler automatically put break statements after each code block in the switch?
Leaving aside the good desire to be able to use the identical block for several cases (which could be special-cased)...
Is it for historical reasons? When would you want multiple code blocks to execute?
It's mainly for compatibility with C, and is arguably an ancient hack from the days of old when goto
keywords roamed the earth. It does enable some amazing things, of course, such as Duff's Device, but whether that's a point in its favor or against is… argumentative at best.
I am now working on project where I am in need of break
in my switch statement otherwise the code won't work. Bear with me and I will give you a good example of why you need break
in your switch statement.
Imagine you have three states, one that waits for the user to enter a number, the second to calculate it and the third to print the sum.
In that case you have:
Looking at the states, you would want the order of exaction to start on state1, then state3 and finally state2. Otherwise we will only print users input without calculating the sum. Just to clarify it again, we wait for the user to enter a value, then calculate the sum and prints the sum.
Here is an example code:
while(1){
switch(state){
case state1:
// Wait for user input code
state = state3; // Jump to state3
break;
case state2:
//Print the sum code
state = state3; // Jump to state3;
case state3:
// Calculate the sum code
state = wait; // Jump to state1
break;
}
}
If we don't use break
, it will execute in this order, state1, state2 and state3. But using break
, we avoid this scenario, and can order in the right procedure which is to begin with state1, then state3 and last but not least state2.
Java comes from C and that is the syntax from C.
There are times where you want multiple case statements to just have one execution path. Below is a sample that will tell you how many days in a month.
class SwitchDemo2 {
public static void main(String[] args) {
int month = 2;
int year = 2000;
int numDays = 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if ( ((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0) )
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
System.out.println("Number of Days = " + numDays);
}
}
As far as the historical record goes, Tony Hoare invented the case statement in the 1960s, during the "structured programming" revolution. Tony's case statement supported multiple labels per case and automatic exit with no stinking break
statements. The requirement for an explicit break
was something that came out of the BCPL/B/C line. Dennis Ritchie writes (in ACM HOPL-II):
For example, the endcase that escapes from a BCPL switchon statement was not present in the language when we learned it in the 1960s, and so the overloading of the break keyword to escape from the B and C switch statement owes to divergent evolution rather than conscious change.
I haven't been able to find any historical writings about BCPL, but Ritchie's comment suggests that the break
was more or less a historical accident. BCPL later fixed the problem, but perhaps Ritchie and Thompson were too busy inventing Unix to be bothered with such a detail :-)