Statements are executed for their effect and have no value. The body of every method,
constructor, initialiser and block lambda is a block of statements (JLS chapter 14).
The switch statement has its own page,
Switch, and try and
throw are on Exceptions.
Normal and abrupt completion
Every statement either completes normally, and execution goes on to the next statement, or completes abruptly for a reason (JLS 14.1):
| Reason | Caused by |
|---|---|
| A break, with or without a label | break |
| A continue, with or without a label | continue |
| A return, with or without a value | return |
| A yield, with a value | yield in a switch expression |
| A throw, with an exception | throw, or an expression that throws |
If a statement contains another that completes abruptly, the outer one usually
completes abruptly for the same reason, until a statement that handles it: a loop or
labelled statement for break and continue, a method for
return, a switch expression for yield, a try
for a throw.
Blocks and local declarations
Block:
{ [BlockStatements] }
BlockStatement:
LocalClassOrInterfaceDeclaration
LocalVariableDeclarationStatement
Statement
LocalVariableDeclaration:
{VariableModifier} LocalVariableType VariableDeclaratorList
LocalVariableType:
UnannType | var
- A block runs its statements in order. Variables and local classes declared in it are in scope from their declaration to the end of the block.
- The only modifiers of a local variable are
finaland annotations. - Local classes, and since Java 16 local enums, records and interfaces, may be
declared in a block. Local enums, records and interfaces are implicitly
static. - A local variable declaration is not a statement on its own: it cannot be the body
of an
ifor a loop without braces.if (x) int y = 1;is an error.
Every statement
| Statement | Form | JLS |
|---|---|---|
| Empty | ; | 14.6 |
| Labelled | label: Statement | 14.7 |
| Expression | x = 1;, i++;, f();, new T(); | 14.8 |
if | if (cond) S, if (cond) S else S | 14.9 |
assert | assert cond;, assert cond : detail; | 14.10 |
switch | switch (x) { … } | 14.11 |
while | while (cond) S | 14.12 |
do | do S while (cond); | 14.13 |
Basic for | for (init; cond; update) S | 14.14.1 |
Enhanced for | for (T x : expr) S | 14.14.2 |
break | break;, break label; | 14.15 |
continue | continue;, continue label; | 14.16 |
return | return;, return expr; | 14.17 |
throw | throw expr; | 14.18 |
synchronized | synchronized (expr) Block | 14.19 |
try | try Block catch … finally …, try (resources) … | 14.20 |
yield | yield expr; | 14.21 |
| Block | { … } | 14.2 |
Expression statements
Only some expressions may be used as statements: assignments (including compound
ones), ++ and -- in prefix or postfix form, method calls and
class instance creations. x + 1; and a == b; are errors. The
result of a method call used as a statement is discarded.
if
The condition must be of type boolean or Boolean. An
else belongs to the nearest if that has none, so braces are
needed to attach it to an outer one:
if (a)
if (b) x();
else y(); // belongs to "if (b)", whatever the indentation says
if (n < 0) {
sign = -1;
} else if (n == 0) {
sign = 0;
} else {
sign = 1;
}
assert
assert (Java 1.4) checks a condition when assertions are enabled, and
throws AssertionError if it is false, with the optional second expression
as the message. Assertions are disabled by default; java -ea enables them
(-ea:com.example... for one package tree), and -esa for the
system classes. When disabled, the expressions are not evaluated, so they should have
no side effects.
assert index >= 0 && index < size : "index " + index + " out of range";
Loops
while (it.hasNext()) process(it.next()); // tests first; may run zero times
do {
line = in.readLine(); // runs at least once
} while (line != null && line.isBlank());
for (int i = 0, j = n - 1; i < j; i++, j--) swap(a, i, j);
for (;;) { … } // no condition: loops until break, return or throw
for (String s : List.of("a", "b")) System.out.println(s); // enhanced for over an Iterable
for (int v : new int[] {1, 2, 3}) total += v; // enhanced for over an array
- The basic
forhas an initialisation (a local variable declaration, or a list of expression statements), an optional condition (missing meanstrue) and a list of update expression statements. Variables declared in the initialisation are in scope only in the loop. - The enhanced
for(Java 5) works on arrays and on anyIterable. Over anIterableit is the same as a loop overexpr.iterator()withhasNext()andnext(); over an array, a loop over the indexes. The loop variable may befinal,var, or unnamed (for (var _ : items) count++;, Java 22). Changing the loop variable does not change the array or collection. - An
Iterablethat isnullthrowsNullPointerException, as does unboxing anullelement into a primitive loop variable.
break, continue and labels
break;leaves the innermostswitch,while,doorfor.break label;leaves the statement with that label, which may be any statement, including a block.continue;ends the current iteration of the innermost loop;continue label;that of the labelled loop. The label must be on a loop.- Neither may jump out of a lambda body, a switch expression, or a class declaration inside the loop.
- Labels have their own namespace; a label may not be redeclared inside the statement it labels.
search:
for (int[] row : grid) {
for (int cell : row) {
if (cell == target) { found = true; break search; }
if (cell < 0) continue search; // skip the rest of this row
}
}
return
return expr; ends a method with a value assignable to its result type;
return; ends a void method, a constructor’s epilogue, or a
lambda whose function type returns void. return is not
allowed in an initialiser, in a compact canonical constructor, in a constructor
prologue, or inside a switch expression. Any finally blocks between the
return and the method run first.
synchronized
synchronized (expr) { … } evaluates expr, which must be a
reference, locks that object’s monitor, runs the block and unlocks it, even if the
block completes abruptly. A null reference throws
NullPointerException. See Threads
and the memory model.
yield
yield expr; (Java 14) gives the value of the enclosing switch
expression from inside a block or a statement group. See
Switch.
Unreachable statements
It is a compile-time error for a statement to be unreachable (JLS 14.22). The analysis is simple and conservative: it treats only constant expressions as known.
- A statement right after
return,throw,break,continueoryieldin the same block is unreachable. while (true) { … }with nobreakthat leaves it cannot complete normally, so code after it is unreachable. The same holds forfor (;;)anddo … while (true).while (false) { … }is an error, because the body is unreachable.ifis treated specially so that it can be used for conditional compilation:if (DEBUG) { … }with a constantfalseis allowed, and the code after anifis always reachable.- A catch clause that cannot be reached, because no exception it handles can be thrown, or because an earlier clause catches a superclass, is an error.
static final boolean DEBUG = false;
void run() {
if (DEBUG) log("start"); // allowed: the compiler may drop it
while (true) {
if (step()) break;
}
finish(); // reachable, because of the break
}