Control Flow
Is the order in which a computer executes a program's instructions, statements, and function calls. It's based on conditions and decisions that determine how a program moves from one instruction to another.
Switch Statement / Expressions
- Are useful for comparing single values but not for ranges.
- No boolean expressions in the "selector expression" nor in the "case expression" are supported.
- Can "see" variables (inside) form before switch statement.
- There are two forms of switch:
- with colon
;(can have fall-through) "Standard Case" or - with arrow
->(NO fall-through) "Arrow Case" .
- with colon
- Both can either:
- execute statements "Switch Statements" (if no match or default, no execution) or
- return an expression "Switch Expression" (MUST always return a value) .
switch (SELECTOR_EXPRESSION) {
case CASE_EXPRESSION : OR -> //LABEL: if SELECTOR match CASE expression, ...
STATEMENT OR EXPRESSION ; //statements are executed or expression returned
break ; //optional (not needed in 'arrow case'), end switch
default : //optional but only once, if no case match
STATEMENT OR EXPRESSION ;
}
The program's execution continues from one case to the next in a standard-case (statement and expression) without a break statement. This can happen even if the expression value of the next case doesn't match.
Because a case can not cover a rang (e.g.: 1-3), multiple case-values can be stacked by separating them with a colon ,. This works on all switch variations (statement, expression, standard, arrow).
E.g.: case 1, 2, 3: has the values 1, 2, and 3.
| switch type | syntax | fall-through logic | Need to return value in any case ? | optional default | stack-case-label |
|---|---|---|---|---|---|
| Standard Statement | : | yes | no | yes | yes |
| Standard Expression | : | yes | yes | yes | yes |
| Arrow Statement | -> | no | no | yes | yes |
| Arrow Expression | -> | no | yes | yes | yes |
"Standard Case" Switch :
as Statement
- Fall-through, executes every statements after a matching "case" till there is a
breakor the switch ends. - If no "case" match then the
defaultis executed if there is one, otherwise nothing happens.
switch ( some_variable ) {
case 1: System.out.print("1 "); break;
case 2:
System.out.print("2 ");
System.out.print("more ");
break;
case 3, 4, 5: System.out.print("stack case label"); break;
case 6: System.out.print("6 ");
case 7: System.out.print("7 ");
default: System.err.print( "default");
}
- line 2:
only print ifsome_variable(1) is matchingcase(1). - line 3-6:
same principe as line 2 but different style and one more statement. - line 7: (stack case label)
only print ifsome_variableis3,4or5, which is matchingcase. - line 8: (fall trough)
print everything ("6 7 default") till the end because there is nobreakwhich end the switch. - line 10:
print ("default") if a case above was not stopped bybreakor if none of the cases matched.
as Expression
- Must always return a value! You can use
defaultto make sure of it or throw an "exception". - Do not forget to terminate the whole statement with an
;. - Use the
yieldkeyword to mark the return value,switchends after. - If a matched
casehas noyield(fall-through), then the code moves on to the next line without checking thecase.
double result = switch ( vari ) {
case 'z' : System.out.print("z"); //if match, 'z' is printed, move on
case 'x', 'y' : yield 100.0; //if match, 'result' is '100.0', exit
default : yield 0; //otherwise 'result' is always '0.0'
}; //must end with ';'
"Arrow" Case ->
- No "fall-through" logic, only one "matching case" is executed even without the
breakkeyword. - Multiple statements need to be wrapped in brackets
{ }.
as Statement
switch ( 42 ) {
case 42 -> System.out.print("42"); //only this statement is executed
case 10 -> { System.out.print("10"); //multiple statements need brackets
System.out.print("You need 32 more."); }
case 1, 2 -> System.out.print("1 or 2"); //stack-case-value
default -> System.out.print("Is not 42 or 10."); //is optional
}
as Expression
- Must always return a value! You can use
defaultto make sure of it or throw an "exception". - Do not forget to terminate the whole statement with an
;. - Mark return value with
yieldif in brackets{ }.
int result = switch (vari) {
case 10 -> vari += 32; //'vari' is '10', 'result' and 'vari' become '42', end switch
default -> {
if (vari > 100)
yield 100; //'vari' bigger then '100', 'result' becomes '100'
else
yield 0;} //'vari' smaller then '100' but not '10', 'result' becomes '0'
};
No Boolean on Switch, use default ?
- You can not use boolean expressions in the "selector expression" or the "case expression".
int val = 1;
switch (val) {
//switch (true) { //selector type boolean not supported
case val < 42 -> System.out.print("42"); //"compiler error!"
}
Error because the case on line 4 evaluates to a boolean. Swapping line 2 with line 3 does not help because booleans are not allowed as "selector expressions".
- But you could use it in brackets, for example in
default.
switch (vari) {
case 100 :
System.out.print("100"); break;
default : {
if (vari > 100)
System.out.print("bigger then 100");
else
System.out.print("less then 100");
}
}
Loops
Loops are used to process certain instructions over and over again.
A loop consists of the "loop condition" and the "loop body".
- "loop condition": is a "boolean expression"
- if
true, the "loop body" is executed once, after the condition is checked again, this creates the loop. - if
false, the "loop body" is not executed and the code continues from after the "loop body".
- if
- "loop body": statements to be executed
breakends the loop, none of the statements in the "loop body" are executed after.continuejumps back to the "loop condition", none of the statements in the "loop body" are executed after thecontinuestatement for that iteration.;or{}means that the there is nothing to be executed, can be because everything has already be done in the "loop condition".- Brackets
{ }are only needed if there are more then one statement (lines) in the loop body.
Is when the loop condition becomes never false, thus the program stuck in a loop till it runs out of memory and crashes.
In some cases the loop supposed to be "broken" from within, thus the "loop condition" is set as "infinite loop",
e.g.: for ( ; ; ;) or for ( ; true; ) or while (true) .
| loop type | syntax |
|---|---|
| while loop | while ( CONDITION ) STATEMENT(S) |
| do while loop | do STATEMENT(S) while ( CONDITION ); |
| for loop | for ( INITIALIZER; CONDITION; UPDATER ) STATEMENT(S) |
| for each loop | for ( DATATYPE EACH : COLLECTION ) STATEMENT(S) |
"While Loop"
- Checks the "loop condition" before executing the "function body".
int number = 1234;
while ( number > 0 ) { //as long 'number' is bigger then 0
number /= 2; //divide by 2 und update number
System.out.println( number ); //print number to the screen
}
int number = 1234;
while ( true ) { //always true
number /= 2; //divide by 2 und update number
if (number <= 0) //if number is '0' or less
break; //then break loop
if (number > 500) //if number is bigger then '500'
continue; //jump back to condition, no next lines
System.out.println( number ); //print number to the screen
}
"Do While Loop"
- No matter if the "loop condition" is
trueorfalse, the "loop body" is always executed at least once at the beginning. - Remember the
;semicolon after thewhilecondition at the end. - Variables which need to be visible to the "loop condition", need to be declared outside the "loop body".
int number = (int) (Math.random() * 5 + 1); //outside loop, otherwise always different
int guess; //declare outside loop, otherwise not ...
//visible to 'while condition' at last line
do {
System.out.println("What number between 1 and 5 do I have in mind?");
guess = new java.util.Scanner( System.in ).nextInt();
if ( number == guess )
System.out.println( "Good guess!" );
else if ( number > guess )
System.out.println("My number is larger than yours!");
else // number < guess
System.out.println("My number is smaller than yours!");
} while ( number != guess ); //code above is executed, after only if 'true'
The user is asked at least once at the beginning for a "number". After the "number" is compared with the "random number" (guess), if the numbers are "not equal" (condition is true) then the "loop body" is executed again and the process repeats as long the numbers do not match (condition is false).
"For Loop"
- Is best used if all 3 values in the "loop condition" are related to the same variable.
for (INITIALIZER ; CONDITION ; UPDATER) {
STATEMENT(S) ;
}
- "INITIALIZER" : to initialize "local variable" for the condition, e.g.:
int i = 0- Variables are only initialize at the first iteration.
- Naming: the "variable name" (
i) is arbitrary but has to be different to the outside identifiers. - Local scope:
int i = 0, the variable is only visible within the loop, need to be initialized with an value! - Outside scope: leave empty if variable from out side the loop is to be used,
e.g.:for ( ;out > 0; out++). - Data type: can be any data type, e.g.:
for (boolean i = true; i; i = false) - Multiple variables: can be more than one but have to be of the same type and separated be
,colon.
e.g.:for (int i = 0, j = 1, z = 2; i < j + z; i++)
- "CONDITION" : to create a condition when the loop should end
- Is evaluated before the statements in the "loop body" are executed, if
true, iterate once the loop, otherwise end. - There can be no more than one condition and it must be a boolean expression.
- Infinite loop, can be empty e.g.:
for (int i = 0; ;i++)ortruee.g.:for (int i = 0;true;i++),
than the loop needs to be broken from within e.g.:break. - "Out side variables" can be used to create a boolean expression.
- Is evaluated before the statements in the "loop body" are executed, if
- "UPDATER" to update the variable for the condition
- Updates (executes) at the end of the loop iteration.
- Multiple variables: can be more than one but have to be separated by
,colon,
e.g.:for (let i = 0, y = 5; i < y; i++, y--) - Can be empty
for (int i = 0; ; ), update or break from within the loop.
Nested Loop
Is a loop that is contained within another loop, and the two loops are referred to as the "outer loop" and the "inner loop". The "outer loop" controls how many times the "inner loop" is fully executed.
for ( int i = 1; i <= 3; i++ ) { //'outer loop', runs the 'inner loop' 3 times
for ( int j = 1; j <= i; j++ ) //'inner loop', runs on every iteration once more, because 'i'
System.out.print( '*' ); //no brackets are needed if only one statement follows
System.out.println();
}
*
**
***
for ( int i = 1, j = 6; i <= j; i++, j-- )
System.out.printf( "%d * %d = %d%n", i, j, i*j );
1 * 6 = 6
2 * 5 = 10
3 * 4 = 12
"Break and Continue Label"
Allows to "jump" to "before" or "after" a "code block" or to break a "nested loop" from within an "inner loop".
NOTE: to many "jumps" can make the code difficult to follow ("Spaghetti code") !
- "label":
- Can be any name but has to be terminated with
:a colon. - Has to come before
breakorcontinue. - Must be right before the "code block" (loop), nothing in between is allowed.
- Can be any name but has to be terminated with
- "break":
- Code continues after the code block which has been marked with the label.
- "continue":
- Code continues from where the label is set, but it works only on loops.
break and continue on loops
label: //code continue from here with 'continue'
// System.out.println("not allowed"); //no code allowed between label and block
while (true) {
System.out.println("looping");
break /* continue */ label; //either 'break' or 'continue', 'continue' courses an 'infinite loop'
System.out.println("Can only be reached with continue");
}
//code continue from here with 'break'
- line 5:
break label;(comment out continue)- Code continues from line 8 because that is where the "labeled" code block ends.
- None of the statements between
breaktill the end of the block is executed.
- line 5:
continue label;(comment out break)- Code continues from line 1 because that is where the "labeled" code block starts.
- The code block must be a loop for continue to work.
while (true) {
outer_loop:
while (true)
break outer_loop;
System.out.println( "Outer loop." );
}
- line 4;
- Code continues from line 5 (is not part of the code block line 3-4), which prints out the message, after the "outer loop" is restarted the cycle starts again (infinite loop).
- If the label 'outer_loop' would have been on line 0, then
breakwould have broken the "outer loop" and there would have not been an 'infinite loop'.
break on code blocks
label:
{
// some code, executed
break label;
// some code, not executed
}
// code continues from here
break "switch-statement"
// cytosine [C], guanine [G], adenine [A] or thymine [T]
String dnaBases = "CGCAGTTCTTCGGXAC";
int a = 0, g = 0, c = 0, t = 0;
loop: //'for loop block' is labeled 'loop'
for ( int i = 0; i < dnaBases.length(); i++ ) {
switch ( dnaBases.charAt( i ) ) {
case 'A', 'a':
a++;
break;
case 'C', 'c':
c++;
break;
case 'G', 'g':
g++;
break;
case 'T', 't':
t++;
break;
default:
System.err.println( "Unknown nucleotide " + dnaBases.charAt( i ) );
break loop;
}
}
The "for loop" iterates through every character of the string dnaBase. The "switch statement" within compares the character with its cases and increments the counters accordantly. If it has no case for it (X) then the default is executed, which prints an error message and breaks.
Without the label, it would only break the "switch-statement" and not the "for loop", but because of it the "for loop" is broken and the code would continue from after with loop labeled "for loop block" (line 24).