- Richard Feynman -
Chapter:Control flow
Contents
Control flow
Meta information about this chapter
Expand using link to the right to see the full content.
Introduction
Control flow is, of course, one of the central concepts in imperative programming. It is important that the students understand the concepts of branching and looping.
Purpose
The purpose of this chapter is to introduce the most basic control flow mechanisms in Java, so that the students can write more interesting programs.
The control flow constructs use blocks to group related code together, which is why we also introduce blocks in this chapter. Blocks are also used for defining classes and methods, which is why this will be useful also later on in the book/course.
Goal
The goal of this chapter is that the students can understand, explain and use:
- the IF statement
- the WHILE statement
- the FOR statement
- the concept of a BLOCK (of code)
- scoping implications of blocks
It is also good if the student can choose between the FOR loop and the WHILE loop and motivate the choice.
Concepts
- Block
- IF (selection, branching)
- WHILE (iteration, loop)
- FOR (iteration, loop)
Instructions to the teacher
Our experience tells us that scoping is hard for many students and should therefore be given some attention when introducing blocks.
Another thing we have learned, is that it seems to work well to introduce the while loop before the for loop. It seems like the steps of the while loop:
- declare variables used in test
- while block start with the test
- change the variables used in the test
- end block
are pretty straight forward to the students. When later on introducing the for loop, you may present it as a more compact way to express the same thing:
for (intitialization; test; change;) { block }
.
However, expect the more diligent students to ask, "so how do I choose between the two?".
Our answer is that, on the one hand, they are indeed equivalent, but on the other hand, there are some subtle nuances which sets the two apart.
One rule of thumb can be: "If you know how many times you need to iterate, then use a for loop in order to make your statement clearer. If you don't know or can predict how many iterations are needed, use a while loop."
Another rule of thumb can be "If you don't need the loop variable to be in scope after the loop, you may use the for loop. If you need to use the loop variable also after the loop (and possibly even before), then use a while loop."
A related rule could be: "If you don't care about a loop variable, but rather want to iterate over some collection of objects - like a list or an array - then you may use a for-each-loop".
We have a section below about the for-each-loop (also known as "the enhanced for loop").
Lastly, we strongly suggest that you follow our style (also supported by many coding style guides) to always use curly braces around the body of IF, FOR, and, WHILE statements, even if they only have one single statement in their body. The only reason to leave out the curlies, in our opinion, is to show off that you know that you can leave them out. In our experience, it is begging for future problems (when more statements are added) and adds unnecessary complexity for the students. Heck, we think it is fine to tell them that they should always use curly braces (not exactly the same as the not so true claim that they must do so), in connection to IF, WHILE and FOR.
About leaving out curlies for control statements that have only one statement in their body, that is a rule which the students really don't need to learn at a beginners level. There's nothing wrong with showing them that it works, but if you do so, please tell them it is considered bad style. The rule might be confusing to students, because it only applies to certain constructs. You cannot, for instance, have a method without curlies, just because the method only has one single statement. Likewise, you cannot declare a class without curlies, just because it only has one statement.
Common problems
We'll get back to this point, at a later time. Promise!
Chapter videos
All videos in this chapter:
- English: Control statements/control flow (Full playlist) | Code block | Control flow statements - introduction and IF | Control flow - the while statement | Control flow - the for statement | Control flow - miscellaneous constructs | Java Extra - for each
- Swedish: Flödeskontroll (Full playlist) | Kodblock | Flödeskontroll - introduktion och IF-satsen | Flödeskontroll - while-satsen | Flödeskontroll - for-satsen | Flödeskontroll - diverse andra konstruktioner för flödeskontroll
Lecture presentations (PDF):
See below for individual links (also slides) to the videos.
Block
Description
When we want to group together code, most often because it belongs together in some way, we use block (or code block). You Start a block with { and end it with }. All code in between is said to be the code block. The block could actually be empty but most often it contains one or more statements/instructions.
Note that variables declared inside a block of code are only visible (can only be used) inside the same block (or inside blocks declared inside the same block).
Videos and slides
Extra - Indentation
It is important that your code follow a familiar and standard style, so that people (including teachers) easily can read you code and quickly see the structure of it. An important part of the style is the way you indent your code.
Now that you know what a block of code is, you should spend some time and effort on making your code tidy. There are some style guides to follow when writing code in blocks.
First, your block starts with a left curly brace, {
. This curly brace typically sits at the end of the line starting a block. All code inside the block, starts at a few spaces in. The block ends with a right curly brace, }
, but that curly brace is left of the code inside the block. Let's look at some examples:
public class Carpet { // <--- here's a start of a block
int length; // all statements in the block start at e.g. two spaces in
double weight;
String itemNumber;
Color color;
} // <--- here's the end of the block
We will talk more about indentation at each sub section below.
Control flow introduction and if statement
Description
Let's start by a human example. If my shoelaces are not tied properly, I will tie them. This means I will only tie my shoelaces if they're not tied. With this simple example we want to show that we use if statements in our daily life all the time.
The IF-statement is a control flow construct that we can use if we want to execute a block of code only if a boolean expression is true. In its simplest form we write code with an if
statement like this:
if (temperature>40) {
System.out.println("Please, turn on the fan");
}
In this example we print "Please, turn on the fan" if the temperature (the value of the variable temperature) is higher than 40. If the temperature is less than (or equal) to 40 we do nothing.
A slightly more complex if statement:
if (temperature>40) {
System.out.println("Please, turn on the fan");
} else {
System.out.println("You do not need to turn on the fan");
}
We added code that is executed if the temperature is NOT higher than 40. We did this by adding else
in the if statement.
Our final example will be:
if (temperature>40) {
System.out.println("Please, turn the fan to MAX.");
} else if (temperature>30){
System.out.println("Please, turn on the fan modestly");
} else {
System.out.println("You do not need to turn on the air condition");
}
In this last example, we first check if the temperate is higher than 40. If it is, we output "Please, turn the fan to MAX." None of the other clauses of the if statement would execute. But if the temperature is NOT higher than 40 we continue and check if the temperature is higher then 30. If it is we output "Please, turn on the fan modestly" (and nothing else). If the temperature is not higher than 30 (or 40 for that matter) we output "You do not need to turn on the air condition".
Indentation for the IF statement
Note that the style for the if statement follows the style for blocks in general. In Java, we put the starting curly brace at the same line as the if header:
if ( printer.hasPaper() ) { // <--- here the if-block starts
printJob.print();
} // here, the if-block ends
As you see, the end curly brace starts at the same column as the if statement header (under the "i" of "if").
Most editors will help you get the indentation right. In Atom, for instance, you can highlight all text in your Java-file and then go to the Edit menu, choose Lines sub menu, and then choose the Auto-indent menu option. In most cases, Atom will help you re-indent your whole file (the text you have highlighted).
But you should learn to get the indentation right from the start, since it will help you get successful as both a student and as a professional programmer. Most projects (or companies) adhere to some coding style standard. So details may vary. But you should always be consistent and follow one style consistently.
As a detail about the if-statement, we follow a style which mandates that there should be some spaces surrounding the if parentheses with the boolean expression. One space after the word "if" and one space before the opening curly brace for the block.
With the if-else the style looks like the following:
if ( printer.hasPaper() ) { // <--- here the if-block starts
printJob.print();
} else { // else block starts here, on the same line as the closing curly for the if block
printer.signal(Signals.OUT_OF_PAPER); // the statements in the else block are on the same column
} // as those of the if block
If-else-if-else looks like the following:
if ( printer.hasLotsOfPaper() ) { // <--- here the if-block starts
printJob.print();
} else if (printer.hasLowPaperStock() ) { // else if block starts here, on the same line as the closing curly
printer.signal(Signals.LOW_PAPER_STOCK); // the statements in the else-if block are on the same column as blocks above
} else { // note where the curlies are, and also note the surrounding space
printer.signal(Signals.OUT_OF_PAPER);
}
Videos and slides
while
Description
A while loop is a construct in a programming language that allows code to be repeated as long as a boolean expression is true.
An example:
1 int counter = 3;
2 while (counter > 0 ) {
3 System.out.println("Hi there!");
4 counter--; // decrease the value of counter so that we eventually will exit the loop
5 }
Let's go through the example:
- we declare and initialise (the first assignment) an integer variable,
counter
- we start a while loop. This line means that we will keep looping/repeating as long as
counter > 0
. With the{
we mark the beginning of the block to be executed for every loop. - We simply output the text "Hi there!"
- The last thing we do in the block is the decrementing of
counter
so that the test will yeald false eventually - End of the block of code to be executed in every loop
In the example above "Hi there!" will be printed 3 times. That is because we start with a value of 3 for counter
and decrement it by one each iteration. The value will be, in order:
- 3 --- 3 > 0 is true
- 2 --- 2 > 0 is true
- 1 --- 1 > 0 is true
- 0 --- 0 > 0 is false - we won't enter the block here
Note that counter
will finish at 0 and have the value 0 after the loop.
Indentation for the while-statement
The indentation of the while-statement, is pretty much the same as for a simple if-statement:
while ( printer.hasMorePaper() ) { // curly starts at the same line as the while-statement
printer.print(printJob.nextPaper()); // statements in the block are indented
} // end-curly under the "w" of the while-statement
Note the space after "while" before the boolean expression, and before the start curly brace for the block.
Videos and slides
for
Description
The for
statement (loop) is typically used when you know how many times you want to do something repeatedly. Think of programs that offers to repeat some boring task for you, and you, the user provides input for how many times the program should do it.
Then the program would read your input into a variable, and use that variable inside a for loop.
As with the while
loop the for
statement is used to loop (repeat) a block of code. The following code:
1 for (int i=0; i<3; i++) {
2 System.out.println("Hi there!");
3 }
outputs "Hi there!" three times. How? Let's go through the code:
- we start be declaring a
for
loop-
int i=0
means we declare a variable. This is done before we start looping -
i<3
means we will loop as long asi<3
-
i++
means that for every loop we doi++
(as the last thing in the block) -
{
defines the start of the block to be executed in each loop
-
-
System.out.println("Hi there!");
outputs "Hi there!" -
}
closes the block to be executed in each loop.
Slightly more formally we can say that a for statement looks like this:
1 for (INITIALIZATION; CONDITION; CHANGE) {
2 /* the code to execute for each loop */
3 }
- INITIALIZATION declares a (local to the for block) variable and initializes it to some start value. This is executed only once.
- CONDITION is the check of a boolean expression - typically a conditional expression involving the variable
- CHANGE is what should happen with the variable every iteration - the change ensures that the condition will be false at some point so that the looping stops
Bonus for the students who run Bash inside a terminal!
Did you know that also Bash offers the for loop construct?
You might know that the command echo
in bash is for printing out text to standard out (typically to the terminal you are working in).
Let's say you want - for some totally weird reason - print your user name to the screen ten times. You can use echo
in a for loop directly in your terminal (running bash) like this:
for ((i=0; i < 10; i++))
do
echo "$USER"
done
You may wonder what the $USER
is, but that's just an environment variable Bash uses to store the current user's user name in.
Let's say that you want to print out the current time and date 10 times, once each second. You can use the date
command to print the time and date. And you can use the sleep n
command to sleep (do nothing) n seconds. So, what if we use a for loop to loop ten times, and in each loop iteration issue the date
command, and then sleep 1
?
This is what you can try:
for ((i=0; i < 10; i++))
do
date
sleep 1
done
If you'd like, you can do all that on one single command line in Bash:
for ((i=0; i < 10; i++)); do date; sleep 1; done
Again, it is typical to use a for loop, when you know how many times you want to repeat doing something, because the for loop makes that clear, as it has become an idiom (something that many people know by heart and often use).
Indentation for the for-statement
Here's the indentation of the for statement - same as for block, if, and while!
for (int i = 0; i < printJob.numberOfPapers(); i++) {
printer.print(printJob.paper(i));
}
Note that blocks can be nested, as we said in the lecture on blocks! Here's a for-statement with a nested if-statement. See how the indentation level increases with each block:
for (int i = 0; i < printJob.numberOfPapers(); i++) {
if ( printer.hasMorePapers() ) {
printer.print(printJob.paper(i));
} else {
printer.signal(Signals.OUT_OF_PAPER);
printJob.setCancelledAt(i);
} // end if-else
}// end for
Videos and slides
for-each-loop
Since Java version 1.5 you can also, apart from the for loop, use the so called for-each-loop in references to Iterable objects (typically collections such as ArrayList):
for (Type item : iterableReferenceVariable) {
// Do something to item
}
Let's look at the following example of a classic for loop:
List<String> someList = someMethodReturningAListOfStrings();
for (int item=0; item<someList.size(); i++) {
String s = someList.get(item);
System.out.println(s.toLowerCase());
}
The code above would print each String in the list with all letters in lower case. Now we should do a similar thing using the for each-loop. Before you look at the code below we would like you to take special notice of the following parts of the for loop above: String s
, someList
and System.out.println(s.toLowerCase())
.
An example using a list of String references could look like this:
List<String> someList = someMethodReturningAListOfStrings();
for (String item : someList) {
System.out.println(item.toLowerCase());
}
The code above would also print each String in the list with all letters in lower case. You can hopefully see some similarities in the for loop above (String s
, someList
and System.out.println(s.toLowerCase())
).
Indentation for the for-each-loop
The enhanced for loop (popularly also known as the "for-each-loop"), follows the same pattern as block, if, while and for.
Note where we put the spaces. Spaces around stuff is not part of the indentation itself, of course, but it is part of the style and readability of the code.
for (Paper currentPaper : printJob.papers()) {
printer.print(currentPaper);
}
Videos and slides
Misc
There are actually some more control flow constructs in Java:
- do-while (iterate at least one time, do test at the end of the block)
- try-catch-finally and throw (material for later lectures - not a control flow per se, but affects the control flow)
-
break
andcontinue
(adds special behavior to loops) - switch-case (a streamlined kind of multiple choice as alternative to long IF statements)
Summary
In this book, we use the Java programming language and the only available control flow statements in Java are:
Choice/decision making:
-
if-then
-
if-then-else
-
switch
Looping/iteration:
-
for
-
while
-
do-while
- for-each-loop (a.k.a. enhanced for-loop) look on this page for a link to a lecture on this kind of loop!
Branching statements:
-
break
-
continue
-
return
Throwing an exception (see later chapter) could be considered a form of branching, but shouldn't be used as a form of flow control. Exceptions have another use, related to error handling.
This chapter focuses only on the following: if-then
, if-then-else
, for
, while
.
Questions and Answers
Q: “The for loop and the while loop seem to do the same thing. When should we use the one and when should we use the other?”
A: You may use the one you feel most comfortable with. If you want a hint of when to use for and when to use while, there is a recommendation that in situation when you know beforehand how many iterations you want, you should use the for loop. It could make the program easier to read and understand. When you don’t know how many iterations you want (for instance if your program is reading lines of text from a file and you don’t know how many lines there are in the file), it is probably more clear to use the while loop. When you read the code out loud, it could better match the way we think and speak. An example of reading out loud the line counting loop, could be “While we haven’t reached the end-of-file, read one more line and increase numberOfLines with one”. If we want to print ten copies of a document, we could use for and such a piece of programming could be read out loud like this, perhaps: “For every number between 0 and 9, print a copy and move the counter to the next number”.
As you see, reading out the for statement doesn’t really match the way we think or speak, but there is an alternative syntax for the for loop that we use when we have some kind of list. We’ll revisit the for loop when we have learned about lists, but as a teaser, we can say already that reading out the for loop when iterating over a list reads something like this: “For each element in theList, do something with that element and move on to the next element”.
Q: “Are there any other control flow mechanisms that you haven’t told us about?”
A: Actually, yes. There is a version of the while loop, called “do while”. It works almost like the while loop, but it always execute the statements in the block at least once, because it has the test of the condition at the end of the block.
do {
swingAxeAgainstTree();
} while( tree.isStillStanding() );
The example above could be a simulation of cutting down a tree using an axe. We know that we must swing the axe against the tree at least once. And then we check to see if the tree is still standing. If it is, we repeat until the test fails (and and the tree is down).
To be honest, the do while construct is not very common, since in most situation (like when cutting down trees) there is no harm in doing the test first. That would be like first checking that the tree is standing before starting to swing the axe against it.
Another construct is the Switch statement. It is useful as an alternative to if-else-if statements when we know that there are many possible cases to test. It is quite common but not very hard to learn. We will not require that you know the switch statement but we encourage you to learn it anyway, as an exercise. You can read about it here: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
Q: “Where in a Java program do we use the control flow things?”
A: Almost exclusively in methods and constructors. There are some exceptions to that rule (there are two special kinds of nameless blocks inside classes, but they are outside the scope of this course!) but if you want a rule it would be: Always inside a block, but never directly inside the block of a class (or inside the block of the friends of classes called interfaces and enums).
So you will never see an if statement, for instance, directly in the body of the class block. It is always inside a block that is inside the class block. Remember, the class block is one of the few blocks that can be the outermost blocks in a compilation unit (in a Java source code file).
Links
Further reading
Where to go next
Next page has the exercises for this chapter: Control_flow_-_Exercises
« Previous • Book TOC • Next »