Under certain conditions, we might need to stop a loop, or proceed with the next iteration straight-away omitting the remainder of a block of code, or return from a method.
The branching statements allow us to do this, and we’ve already seen one of them in previous sections.
The return
statement
This statement exits the method that is currently executing and returns the provided value (if any) to the invoking method. So far, all of the methods we’ve seen, for example in the Airplane
class or in the Door
class don’t return any values as they specify a void
return type in their methods.
The return
statement:
-
Must be defined for methods with a non-
void
return type. In this case, thereturn
statement must have a value, for example,return x;
and the data type must correspond to the return type of the method. -
Is optional for methods with a
void
return type. If provided, thereturn
statement must not have a value, for example,return;
. -
Any method can have more than one
return
statement, although certain rules apply that we’ll cover in a later course.
The return statement is a topic on its own and we are covering the basics only in this section!
|
The return statement works at a method level.
|
As an example, let’s define a PerimeterCalculator
class:
public class PerimeterCalculator {
public void printSquarePerimeter(int side) {
if (side <= 0) {
return;
}
System.out.println("The perimeter of a square of side " + side + " is: " + (side * 4));
return;
}
public int squarePerimeter(int side) {
int perimeter = 4 * side;
return perimeter;
}
}
Here, we have a class with two methods, one that prints out the perimeter of a square if the side is greater than 0 (printSquarePerimeter
), and the other one that calculates the perimeter and returns the calculated value (squarePerimeter
).
Let’s use it to see what we get:
In the example project, check the BranchingStatementsApp class.
|
// Examples of the return statement - check the methods in the PerimeterCalculator class
PerimeterCalculator calculator = new PerimeterCalculator();
// first, let's print out the perimeter of a square of side 4:
calculator.printSquarePerimeter(4);
// next, let's try printing out the perimeter of a square of side -1, in this case,
// nothing should be printed out:
calculator.printSquarePerimeter(-1);
// now, let's try using the squarePerimeter method and store the returned value in
// the result variable:
int result = calculator.squarePerimeter(2);
System.out.println("A square of side 2 has a perimeter of: " + result);
Output:
The perimeter of a square of side 4 is: 16
A square of side 2 has a perimeter of: 8
Analysing the method calls to our PerimeterCalculator
In the first two method calls, we are invoking the calculator.printSquarePerimeter(…)
method that has a void
return type. As a result, we don’t get any value back, hence we cannot assign its result to a variable (because in effect, there is no result).
The printSquarePerimeter
method specifies a return;
statement at the end, which is optional. However, it also specifies a return;
statement at the beginning, after checking if the side
parameter is valid.
In the second invocation of the method, calculator.printSquarePerimeter(-1)
, the side
parameter is negative and hence the condition of the if
statement is true. This initial return;
statement causes the method to exit, and as a result the message isn’t printed out in that case. The execution continues on the next line from where we invoked the method, in our case, int result = calculator.squarePerimeter(2);
.
In the last invocation, we are calling method calculator.squarePerimeter(2)
. This method has a non-void
return type, in our case, it indicates that it will return an int
value and as such, the method must have a return
statement with an int
value. In the example, we have return perimeter;
where perimeter
is a variable of type int
.
As the method returns a value, we can make use of this variable as desired. In our case, we are assigning the value to the result
variable, which we then print out as our second message in our output.
The break
statement
This statement has already been introduced in the switch
statement section. As mentioned there, we can use it to terminate the execution of the following control flow statements: switch
, for
, while
and do-while
.
The break statement works at a control flow statement level and it cannot be used with if statements.
|
For example:
int n = 10;
int energy = 3;
for (int i = 0; i < n; i++) {
if (energy > 0) {
System.out.println("I still have " + energy + " energy left!");
energy--;
} else {
System.out.println("I can't do this anymore!");
break;
}
}
Output:
I still have 3 energy left!
I still have 2 energy left!
I still have 1 energy left!
I can't do this anymore!
Analysing the break
statement example
In our example above, we see that we have a variable i
that is iterating from 0
to 10
(the value of n
) and we expect 10 iterations in that case. However, as we have a break
statement, the loop is terminated beforehand, in our case, we base our decision on an energy
variable that is being decreased on every iteration until it reaches a value of 0
.
Once the energy
value reaches a value of 0
, our else
case is executed and the break;
clause is called, causing our loop to terminate.
The example is made up to illustrate the usage of the break
clause. You could argue, that based on what the example is doing, we could have written this instead:
int energy = 3;
for (int i = 0; i < energy; i++) {
System.out.println("I still have " + (energy - i) + " energy left!");
}
System.out.println("I can't do this anymore!");
And you would be right, this generates the same result as in the code before.
In general, loops/statements with a break
clause can be re-written such that there is no break
statement. However, depending on the case, and in more complex cases than in our example above, it can be more readable to make use of the break
statement.
The continue
statement
The continue
statement allows us to stop the current iteration of a loop and skip to the next iteration. It can be used with for
, while
and do-while
statements.
The continue statement works at a control flow statement level and it can only be used with looping statements.
|
For example, the following code will print out the even numbers from 0
to m
(exclusive):
int m = 8;
for (int i = 0; i < m; i++) {
// if the number is odd
if (i % 2 == 1) {
continue;
}
System.out.println("The next even number is: " + i);
}
Output:
The next even number is: 0
The next even number is: 2
The next even number is: 4
The next even number is: 6
Analysing the continue
statement example
In the example code, we are checking if the current value of i
is odd. We do this by checking the remainder of the division by 2, an odd number will have a remainder of 1, hence our if
condition is i % 2 == 1
.
If the number is odd, we’ll execute the continue
statement, and this causes the remainder of the block of code of the for
loop to be skipped and we move to the next iteration.
By doing so, the increment statement of the for loop is executed, in our case, i++
and our loop condition is verified before the next iteration starts.
This causes that:
-
In our first iteration,
i
is0
, and ourif
condition is false as0 % 2
equals 0 and not 1. In this case, thecontinue
statement is not executed and we print out the messageThe next even number is: 0
. -
In our second iteration,
i
is1
. In this case, ourif
condition is true as1 % 2
equals 1, causing thecontinue
statement to be triggered and hence the rest of ourfor
loop’s block of code is skipped. As a result, a message with number1
isn’t printed out. -
An so on…
Similar to the example of the break
clause, you could argue that our example code could have been written like this:
int m = 8;
for (int i = 0; i < m; i += 2) {
System.out.println("The next even number is: " + i);
}
And again, you would be right, the output of both is the same.
Similarly to the case with break
statements, in general, loops with a continue
clause can be re-written such that there is no continue
statement. However, depending on the case, and in more complex cases than in our example above, it can be more readable to make use of the continue
statement.
About nesting
If you have nested loops, the break
and continue
statements operate on the innermost loop they encounter.
For example, if you have a nested for
loop inside a while
loop, and you add a break
statement inside the for
loop, then the for
loop will be terminated, as in the code below:
int j = 1;
while (j <= 2) {
System.out.println("The outer loop is on iteration: " + j);
j++;
for (int k = 1; k <= 4; k++) {
System.out.println(" The inner loop is on iteration: " + k);
break;
}
}
Output:
The outer loop is on iteration: 1
The inner loop is on iteration: 1
The outer loop is on iteration: 2
The inner loop is on iteration: 1
Analysing the nested loop example
In the code above, we have an outer while
loop that iterates twice (with j
having the values of 1
and 2
), and an inner for
loop that iterates k
from 1
to 4
.
Ignoring the break
clause for a moment, we would expect the outer loop’s message twice (which is printed out as expected), and the inner loop’s message four times in each iteration of the outer loop.
Now, taking the break
clause into consideration, it terminates the innermost loop it finds. In the example, this is the for
loop which is terminated early, more precisely, during the first iteration of the inner loop.
Try moving the break statement outside of the for loop, both before and after the for loop and see what results you get!
|
There is a variant of the break and continue statements, called labelled break and labelled continue that we’ll cover in a future course.
|