I was wondering the if if-else statements, is like a switch statement that does have a break statement.
if( boolean_expression_1 )
statement_1
else if( boolean_expression_2 )
statement_2
else
default_statement
Is the same as:
switch( controlling_expression )
{
case: ( boolean_expression_1 )
{
statement_1
break;
}
case: ( boolean_expression_2 )
{
statement_2
break;
}
default:
{
default_statement
}
2
I was wondering the if if-else statements, is like a switch statement that does not have a break statement.
That’s backwards. Kind of.
An if, else if, … else sequence in which all of the tests are all simple equality tests on the same variable of the form (variable == value)
or ((variable == value1) || (variable == value2) ...)
can be converted to a switch statement on that variable. The (variable == value)
tests become case value:
, and the body of the if
(or else if
) becomes the body of the case, but you need to add a break
statement at the end of the case body. The ((variable == value1) || (variable == value2) ...)
tests become a sequence of cases of the form case value1: case value2: ... case valuen:
An if sequence with more complex tests is in general distinct from a switch statement.
If every case in a switch statement ends with break
, that switch statement can always be rewritten as an if, else if, … sequence. This conversion from a switch to an if sequence is also possible when fall through is limited to things such as case A: case B: ... case N: do_something(); break;
Fall through in which a non-empty body falls through to another non-empty body is not directly convertible to an if sequence.
1
Although thinking about an if-else block as being like a switch statement without a break might be a helpful abstraction for a new programmer, it is not a perfect comparison.
Switch is probably closer related to “goto”. Granted, Java doesn’t have Goto, but the language was built upon ideas from other languages like C that did. The “case” and “default” labels are not really any different than any other jump target for a goto statement, so the expected behavior would be to continue executing the next line of code within the block (the entire switch statement is the block). This is explained further in one of the answers on a related question: Why do we have to use break in switch? So we end up with the case that you need a break statement to tell your program you’re done executing this block. You could use break in other types of statements such as a for or while loop similarly.
In languages such as java that use short-circuiting, in an if-elseif-else block, if the condition for the first case of the if statement is true, the else if and else block conditions will not be evaluated. After an if it is expected that you will either find a block of code enclosed braces {} or a single statement. By definition, else means “otherwise” or that the previous condition was not true, it would be a bit contradictory to let the code fall through.
2
Programming languages often provide many different constructs which allow you to express similar logic using different syntax.
if
/else
statements do not “fall through” to each another unconditionally; the else keyword prevents any further else-if
conditions being evaluated just as a break
at the end of a case-block gets you out of a switch, however creating a set of standalone if
s (without using else
) will cause each if
condition to be evaluated on its own.
Coversely, removing the break
keyword from the end of your case
blocks will cause the flow of execution to unconditionally keep falling through to the next case until either a break/return/goto is encountered or the end of the switch block has been reached.
There are (rarely) situations where switch-case fallthrough is considered to be useful; however its more common, and usually more idiomatic to want each case block to be treated on its own.
if-else
and switch-case
are both constructs which allow you to express selection (decision making) in a programming language; sometimes the choice between the two is down to personal style, other times there are compelling reasons to choose one over the other – A similar choice exists when choosing for-vs-while to express repetition.
1
The answer is no – the if-statement is not like a switch-statement without a break. Let us begin with this part of your question:
if boolean_expression_1 was true, would it check if boolean_expression_2 is true?
We can find the answer with this program. The trick is, that we call a method as our boolean_expression and use System.out.println() to see, if the method gets executed. This way we know if the expression was evaluated. Here is the program:
public class IfElseExample {
private static boolean booleanExpression1() {
System.out.println("Expression 1 is being evaluated.");
return true;
}
private static boolean booleanExpression2() {
System.out.println("Expression 2 is being evaluated.");
return true;
}
public static void main(String[] args) {
if (booleanExpression1())
System.out.println("Statement 1 is executed");
else if (booleanExpression2())
System.out.println("Statement 2 is executed");
else
System.out.println("Default statement is executed");
}
}
You will see, that the second boolean expression is not evaluated. This behavior probably becomes more understandable if you put in some brackets (which is a good habit in most cases):
if (booleanExpression1()) {
System.out.println("Statement 1 is executed");
} else {
if (booleanExpression2()) {
System.out.println("Statement 2 is executed");
} else {
System.out.println("Default statement is executed");
}
}
This is the way, the compiler views your original if-chain. As you can see now, the second “if” is a single statement of its own and as such it is not on the same level as the first if-statement. If you chain more if-statements those get nested even deeper.
You also asked, why the switch-statement needs a break statement. This is because the switch-statement is not implemented internally with a chain of if-statement (neither is the if-statement based upon switch-statements). You might expect that
switch(controllingExpression()) {
case 42: System.out.println("A");
case 43: System.out.println("B");
default : System.out.println("z");
}
gets translated by the compiler into something like:
if (controllingExpression() == 42) {
System.out.println("A");
} else if (controllingExpression() == 43) {
System.out.println("B");
} else {
System.out.println("z");
}
This is not the case. Instead it uses a hidden skip-statement:
int x = numberOfStatementsToSkipFor(controllingExpression());
skip x // hidden skip the next x statements byte code instruction
System.out.println("A");
System.out.println("B");
System.out.println("z");
The method numberOfStatementsToSkipFor() returns 0 for 42, 1 for 43 and 2 for everything else. Now it becomes clear why this program might produce
A
B
z
or
B
z
or just
z
but never
A
B
without the ‘z’. But clearly it would be nice if we could do this. And we can by using break which gets translated into another skip statement. So if you put break into all case-branches
switch(controllingExpression()) {
case 42: {
System.out.println("A");
break;
}
case 43: {
System.out.println("B");
break;
}
default : System.out.println("z");
}
the compiler will produce this:
int x = numberOfStatementsToSkip(controllingExpression());
skip x; // hidden skip the next x statements byte code instruction
System.out.println("A");
skip 3; //"B" + skip + "z"
System.out.println("B");
skip 1;
System.out.println("z");
3
To answer the edited question (with the breaks)
They would evaluate the statements the same, if and only if the conditions to enter each block is the same.
To answer the subjective question, of
gives an angle of thought of preserved similarities and also what they are ( different / alike ) deep down
Comparing the two distracts you from what each was designed to quickly express.
A switch
syntactically centralizes the comparison so that you can follow the flow based on its cases.
While an if
describes a single condition to enter a block.
Basically the code just “reads” differently.
For example, you have a word
in your head and you want to look it up in the dictionary.
A switch would read like: hold the starting letter in your head, and then thumb through the alphabet, then give up if it doesn’t start with that letter.
While a bunch of if-else blocks would read like: does word start with letter? repeated many times, then give up.
If you are trying to explain how a switch works to a new programmer (who is familiar with if blocks, it might be easier to explain it as:
if( boolean_expression_1 ) {
statement_1;
return;
}
if( boolean_expression_2 ) {
statement_2;
return;
}
default_statement;
return;
Now the preceding example breaks what is typically taught in schools, but return early and return often is sometimes easier to read, and just as fast in a stack based vm.
There should be optimizations for switches on primitives, so the choice of which to control block to use should be based on what you are comparing.
Remember that lengthy switch
and if
statements tend to become very verbose, hard to maintain, and also degrade in performance as more conditions would have to be checked.
You might want to consider a Hash
of anonymous classes/functions or a command pattern, instead of lengthy control blocks with many conditions.
Hashes and command pattern allows the code to perform faster, and improves the maintainability of the code.