Java if. else Statement
In this tutorial, you will learn about control flow statements using Java if and if. else statements with the help of examples.
In programming, we use the if..else statement to run a block of code among more than one alternatives.
For example, assigning grades (A, B, C) based on the percentage obtained by a student.
- if the percentage is above 90, assign grade A
- if the percentage is above 75, assign grade B
- if the percentage is above 65, assign grade C
1. Java if (if-then) Statement
The syntax of an if-then statement is:
Here, condition is a boolean expression such as age >= 18 .
- if condition evaluates to true , statements are executed
- if condition evaluates to false , statements are skipped
Working of if Statement
Example 1: Java if Statement
Output
In the program, number is false . Hence, the code inside the body of the if statement is skipped.
Note: If you want to learn more about about test conditions, visit Java Relational Operators and Java Logical Operators.
We can also use Java Strings as the test condition.
Example 2: Java if with String
Output
In the above example, we are comparing two strings in the if block.
2. Java if. else (if-then-else) Statement
The if statement executes a certain section of code if the test expression is evaluated to true . However, if the test expression is evaluated to false , it does nothing.
In this case, we can use an optional else block. Statements inside the body of else block are executed if the test expression is evaluated to false . This is known as the if-. else statement in Java.
The syntax of the if. else statement is:
Here, the program will do one task (codes inside if block) if the condition is true and another task (codes inside else block) if the condition is false .
How the if. else statement works?
Example 3: Java if. else Statement
Output
In the above example, we have a variable named number . Here, the test expression number > 0 checks if number is greater than 0.
Since the value of the number is 10 , the test expression evaluates to true . Hence code inside the body of if is executed.
Now, change the value of the number to a negative integer. Let’s say -5 .
If we run the program with the new value of number , the output will be:
Here, the value of number is -5 . So the test expression evaluates to false . Hence code inside the body of else is executed.
3. Java if. else. if Statement
In Java, we have an if. else. if ladder, that can be used to execute one block of code among multiple other blocks.
Here, if statements are executed from the top towards the bottom. When the test condition is true , codes inside the body of that if block is executed. And, program control jumps outside the if. else. if ladder.
If all test expressions are false , codes inside the body of else are executed.
How the if. else. if ladder works?
Example 4: Java if. else. if Statement
Output
In the above example, we are checking whether number is positive, negative, or zero. Here, we have two condition expressions:
- number > 0 — checks if number is greater than 0
- number — checks if number is less than 0
Here, the value of number is 0 . So both the conditions evaluate to false . Hence the statement inside the body of else is executed.
Note: Java provides a special operator called ternary operator, which is a kind of shorthand notation of if. else. if statement. To learn about the ternary operator, visit Java Ternary Operator.
4. Java Nested if..else Statement
In Java, it is also possible to use if..else statements inside an if. else statement. It’s called the nested if. else statement.
Here’s a program to find the largest of 3 numbers using the nested if. else statement.
Example 5: Nested if. else Statement
Output:
In the above programs, we have assigned the value of variables ourselves to make this easier.
However, in real-world applications, these values may come from user input data, log files, form submission, etc.
Java if statement with exception
Table of Contents
The sequence of execution of a program is controlled by statements , which are executed for their effect and do not have values.
Some statements contain other statements as part of their structure; such other statements are substatements of the statement. We say that statement S immediately contains statement U if there is no statement T different from S and U such that S contains T and T contains U . In the same manner, some statements contain expressions (§15 (Expressions)) as part of their structure.
The first section of this chapter discusses the distinction between normal and abrupt completion of statements (§14.1). Most of the remaining sections explain the various kinds of statements, describing in detail both their normal behavior and any special treatment of abrupt completion.
Blocks are explained first (§14.2), followed by local class declarations (§14.3) and local variable declaration statements (§14.4).
Next a grammatical maneuver that sidesteps the familiar «dangling else» problem (§14.5) is explained.
The last section (§14.21) of this chapter addresses the requirement that every statement be reachable in a certain technical sense.
14.1. Normal and Abrupt Completion of Statements
Every statement has a normal mode of execution in which certain computational steps are carried out. The following sections describe the normal mode of execution for each kind of statement.
If all the steps are carried out as described, with no indication of abrupt completion, the statement is said to complete normally . However, certain events may prevent a statement from completing normally:
The break (§14.15), continue (§14.16), and return (§14.17) statements cause a transfer of control that may prevent normal completion of statements that contain them.
Evaluation of certain expressions may throw exceptions from the Java Virtual Machine (§15.6). An explicit throw (§14.18) statement also results in an exception. An exception causes a transfer of control that may prevent normal completion of statements.
If such an event occurs, then execution of one or more statements may be terminated before all steps of their normal mode of execution have completed; such statements are said to complete abruptly .
An abrupt completion always has an associated reason , which is one of the following:
A break with no label
A break with a given label
A continue with no label
A continue with a given label
A return with no value
A return with a given value
A throw with a given value, including exceptions thrown by the Java Virtual Machine
The terms «complete normally» and «complete abruptly» also apply to the evaluation of expressions (§15.6). The only reason an expression can complete abruptly is that an exception is thrown, because of either a throw with a given value (§14.18) or a run-time exception or error (§11 (Exceptions), §15.6).
If a statement evaluates an expression, abrupt completion of the expression always causes the immediate abrupt completion of the statement, with the same reason. All succeeding steps in the normal mode of execution are not performed.
Unless otherwise specified in this chapter, abrupt completion of a substatement causes the immediate abrupt completion of the statement itself, with the same reason, and all succeeding steps in the normal mode of execution of the statement are not performed.
Unless otherwise specified, a statement completes normally if all expressions it evaluates and all substatements it executes complete normally.
14.2. Blocks
A block is a sequence of statements, local class declarations, and local variable declaration statements within braces.
A block is executed by executing each of the local variable declaration statements and other statements in order from first to last (left to right). If all of these block statements complete normally, then the block completes normally. If any of these block statements complete abruptly for any reason, then the block completes abruptly for the same reason.
14.3. Local Class Declarations
A local class is a nested class (§8 (Classes)) that is not a member of any class and that has a name (§6.2, §6.7).
All local classes are inner classes (§8.1.3).
Every local class declaration statement is immediately contained by a block (§14.2). Local class declaration statements may be intermixed freely with other kinds of statements in the block.
It is a compile-time error if a local class declaration contains any of the access modifiers public , protected , or private (§6.6), or the modifier static (§8.1.1).
The scope and shadowing of a local class declaration is specified in §6.3 and §6.4.
Example 14.3-1. Local Class Declarations
Here is an example that illustrates several aspects of the rules given above:
The first statement of method foo creates an instance of the member class Global.Cyclic rather than an instance of the local class Cyclic , because the statement appears prior to the scope of the local class declaration.
The fact that the scope of a local class declaration encompasses its whole declaration (not only its body) means that the definition of the local class Cyclic is indeed cyclic because it extends itself rather than Global.Cyclic . Consequently, the declaration of the local class Cyclic is rejected at compile time.
Since local class names cannot be redeclared within the same method (or constructor or initializer, as the case may be), the second and third declarations of Local result in compile-time errors. However, Local can be redeclared in the context of another, more deeply nested, class such as AnotherLocal .
The final declaration of Local is legal, since it occurs outside the scope of any prior declaration of Local .
14.4. Local Variable Declaration Statements
A local variable declaration statement declares one or more local variable names.
See §8.3 for UnannType . The following productions from §4.3, §8.4.1, and §8.3 are shown here for convenience:
Every local variable declaration statement is immediately contained by a block. Local variable declaration statements may be intermixed freely with other kinds of statements in the block.
Apart from local variable declaration statements, a local variable declaration can appear in the header of a for statement (§14.14) or try -with-resources statement (§14.20.3). In these cases, it is executed in the same manner as if it were part of a local variable declaration statement.
The rules for annotation modifiers on a local variable declaration are specified in §9.7.4 and §9.7.5.
It is a compile-time error if final appears more than once as a modifier for a local variable declaration.
14.4.1. Local Variable Declarators and Types
Each declarator in a local variable declaration declares one local variable, whose name is the Identifier that appears in the declarator.
If the optional keyword final appears at the start of the declaration, the variable being declared is a final variable (§4.12.4).
The declared type of a local variable is denoted by UnannType if no bracket pairs appear in UnannType and VariableDeclaratorId , and is specified by §10.2 otherwise.
A local variable of type float always contains a value that is an element of the float value set (§4.2.3); similarly, a local variable of type double always contains a value that is an element of the double value set. It is not permitted for a local variable of type float to contain an element of the float-extended-exponent value set that is not also an element of the float value set, nor for a local variable of type double to contain an element of the double-extended-exponent value set that is not also an element of the double value set.
The scope and shadowing of a local variable declaration is specified in §6.3 and §6.4.
14.4.2. Execution of Local Variable Declarations
A local variable declaration statement is an executable statement. Every time it is executed, the declarators are processed in order from left to right. If a declarator has an initializer, the initializer is evaluated and its value is assigned to the variable.
If a declarator does not have an initializer, then every reference to the variable must be preceded by execution of an assignment to the variable, or a compile-time error occurs by the rules of §16 (Definite Assignment).
Each initializer (except the first) is evaluated only if evaluation of the preceding initializer completes normally.
Execution of the local variable declaration completes normally only if evaluation of the last initializer completes normally.
If the local variable declaration contains no initializers, then executing it always completes normally.
14.5. Statements
There are many kinds of statements in the Java programming language. Most correspond to statements in the C and C++ languages, but some are unique.
As in C and C++, the if statement of the Java programming language suffers from the so-called «dangling else problem,» illustrated by this misleadingly formatted example:
The problem is that both the outer if statement and the inner if statement might conceivably own the else clause. In this example, one might surmise that the programmer intended the else clause to belong to the outer if statement.
The Java programming language, like C and C++ and many programming languages before them, arbitrarily decrees that an else clause belongs to the innermost if to which it might possibly belong. This rule is captured by the following grammar:
The following productions from §14.9 are shown here for convenience:
Statements are thus grammatically divided into two categories: those that might end in an if statement that has no else clause (a «short if statement») and those that definitely do not.
Only statements that definitely do not end in a short if statement may appear as an immediate substatement before the keyword else in an if statement that does have an else clause.
This simple rule prevents the «dangling else » problem. The execution behavior of a statement with the «no short if » restriction is identical to the execution behavior of the same kind of statement without the «no short if » restriction; the distinction is drawn purely to resolve the syntactic difficulty.
14.6. The Empty Statement
An empty statement does nothing.
Execution of an empty statement always completes normally.
14.7. Labeled Statements
Statements may have label prefixes.
The Identifier is declared to be the label of the immediately contained Statement .
Unlike C and C++, the Java programming language has no goto statement; identifier statement labels are used with break or continue statements (§14.15, §14.16) appearing anywhere within the labeled statement.
The scope of a label of a labeled statement is the immediately contained Statement .
It is a compile-time error if the name of a label of a labeled statement is used within the scope of the label as a label of another labeled statement.
There is no restriction against using the same identifier as a label and as the name of a package, class, interface, method, field, parameter, or local variable. Use of an identifier to label a statement does not obscure (§6.4.2) a package, class, interface, method, field, parameter, or local variable with the same name. Use of an identifier as a class, interface, method, field, local variable or as the parameter of an exception handler (§14.20) does not obscure a statement label with the same name.
A labeled statement is executed by executing the immediately contained Statement .
If the statement is labeled by an Identifier and the contained Statement completes abruptly because of a break with the same Identifier , then the labeled statement completes normally. In all other cases of abrupt completion of the Statement , the labeled statement completes abruptly for the same reason.
Example 14.7-1. Labels and Identifiers
The following code was taken from a version of the class String and its method indexOf , where the label was originally called test . Changing the label to have the same name as the local variable i does not obscure the label in the scope of the declaration of i . Thus, the code is valid.
The identifier max could also have been used as the statement label; the label would not obscure the local variable max within the labeled statement.
14.8. Expression Statements
Certain kinds of expressions may be used as statements by following them with semicolons.
An expression statement is executed by evaluating the expression; if the expression has a value, the value is discarded.
Execution of the expression statement completes normally if and only if evaluation of the expression completes normally.
Unlike C and C++, the Java programming language allows only certain forms of expressions to be used as expression statements. For example, it is legal to use a method invocation expression (§15.12):
but it is not legal to use a parenthesized expression (§15.8.5):
Note that the Java programming language does not allow a «cast to void » — void is not a type — so the traditional C trick of writing an expression statement such as:
does not work. On the other hand, the Java programming language allows all the most useful kinds of expressions in expression statements, and it does not require a method invocation used as an expression statement to invoke a void method, so such a trick is almost never needed. If a trick is needed, either an assignment statement (§15.26) or a local variable declaration statement (§14.4) can be used instead.
14.9. The if Statement
The if statement allows conditional execution of a statement or a conditional choice of two statements, executing one or the other but not both.
The Expression must have type boolean or Boolean , or a compile-time error occurs.
14.9.1. The if — then Statement
An if — then statement is executed by first evaluating the Expression . If the result is of type Boolean , it is subject to unboxing conversion (§5.1.8).
If evaluation of the Expression or the subsequent unboxing conversion (if any) completes abruptly for some reason, the if — then statement completes abruptly for the same reason.
Otherwise, execution continues by making a choice based on the resulting value:
If the value is true , then the contained Statement is executed; the if — then statement completes normally if and only if execution of the Statement completes normally.
If the value is false , no further action is taken and the if — then statement completes normally.
14.9.2. The if — then — else Statement
An if — then — else statement is executed by first evaluating the Expression . If the result is of type Boolean , it is subject to unboxing conversion (§5.1.8).
If evaluation of the Expression or the subsequent unboxing conversion (if any) completes abruptly for some reason, then the if — then — else statement completes abruptly for the same reason.
Otherwise, execution continues by making a choice based on the resulting value:
If the value is true , then the first contained Statement (the one before the else keyword) is executed; the if — then — else statement completes normally if and only if execution of that statement completes normally.
If the value is false , then the second contained Statement (the one after the else keyword) is executed; the if — then — else statement completes normally if and only if execution of that statement completes normally.
14.10. The assert Statement
An assertion is an assert statement containing a boolean expression. An assertion is either enabled or disabled . If an assertion is enabled, execution of the assertion causes evaluation of the boolean expression and an error is reported if the expression evaluates to false . If the assertion is disabled, execution of the assertion has no effect whatsoever.
To ease the presentation, the first Expression in both forms of the assert statement is referred to as Expression1 . In the second form of the assert statement, the second Expression is referred to as Expression2 .
It is a compile-time error if Expression1 does not have type boolean or Boolean .
In the second form of the assert statement, it is a compile-time error if Expression2 is void (§15.1).
An assert statement that is executed after its class or interface has completed initialization is enabled if and only if the host system has determined that the top level class or interface that lexically contains the assert statement enables assertions.
Whether a top level class or interface enables assertions is determined no later than the earliest of i) the initialization of the top level class or interface, and ii) the initialization of any class or interface nested in the top level class or interface. Whether a top level class or interface enables assertions cannot be changed after it has been determined.
An assert statement that is executed before its class or interface has completed initialization is enabled.
This rule is motivated by a case that demands special treatment. Recall that the assertion status of a class is set no later than the time it is initialized. It is possible, though generally not desirable, to execute methods or constructors prior to initialization. This can happen when a class hierarchy contains a circularity in its static initialization, as in the following example:
Invoking Baz.testAsserts() causes Baz to be initialized. Before this can happen, Bar must be initialized. Bar ‘s static initializer again invokes Baz.testAsserts() . Because initialization of Baz is already in progress by the current thread, the second invocation executes immediately, though Baz is not initialized (§12.4.2).
Because of the rule above, if the program above is executed without enabling assertions, it must print:
A disabled assert statement does nothing. In particular, neither Expression1 nor Expression2 (if it is present) are evaluated. Execution of a disabled assert statement always completes normally.
An enabled assert statement is executed by first evaluating Expression1 . If the result is of type Boolean , it is subject to unboxing conversion (§5.1.8).
If evaluation of Expression1 or the subsequent unboxing conversion (if any) completes abruptly for some reason, the assert statement completes abruptly for the same reason.
Otherwise, execution continues by making a choice based on the value of Expression1 :
If the value is true , no further action is taken and the assert statement completes normally.
If the value is false , the execution behavior depends on whether Expression2 is present:
If Expression2 is present, it is evaluated. Then:
If the evaluation completes abruptly for some reason, the assert statement completes abruptly for the same reason.
If the evaluation completes normally, an AssertionError instance whose «detail message» is the resulting value of Expression2 is created. Then:
If the instance creation completes abruptly for some reason, the assert statement completes abruptly for the same reason.
If the instance creation completes normally, the assert statement completes abruptly by throwing the newly created AssertionError object.
If Expression2 is not present, an AssertionError instance with no «detail message» is created. Then:
If the instance creation completes abruptly for some reason, the assert statement completes abruptly for the same reason.
If the instance creation completes normally, the assert statement completes abruptly by throwing the newly created AssertionError object.
Typically, assertion checking is enabled during program development and testing, and disabled for deployment, to improve performance.
Because assertions may be disabled, programs must not assume that the expressions contained in assertions will be evaluated. Thus, these boolean expressions should generally be free of side effects. Evaluating such a boolean expression should not affect any state that is visible after the evaluation is complete. It is not illegal for a boolean expression contained in an assertion to have a side effect, but it is generally inappropriate, as it could cause program behavior to vary depending on whether assertions were enabled or disabled.
In light of this, assertions should not be used for argument checking in public methods. Argument checking is typically part of the contract of a method, and this contract must be upheld whether assertions are enabled or disabled.
A secondary problem with using assertions for argument checking is that erroneous arguments should result in an appropriate run-time exception (such as IllegalArgumentException , ArrayIndexOutOfBoundsException , or NullPointerException ). An assertion failure will not throw an appropriate exception. Again, it is not illegal to use assertions for argument checking on public methods, but it is generally inappropriate. It is intended that AssertionError never be caught, but it is possible to do so, thus the rules for try statements should treat assertions appearing in a try block similarly to the current treatment of throw statements.
14.11. The switch Statement
The switch statement transfers control to one of several statements depending on the value of an expression.
The type of the Expression must be char , byte , short , int , Character , Byte , Short , Integer , String , or an enum type (§8.9), or a compile-time error occurs.
The body of a switch statement is known as a switch block . Any statement immediately contained by the switch block may be labeled with one or more switch labels , which are case or default labels. Every case label has a case constant, which is either a constant expression or the name of an enum constant. Switch labels and their case constants are said to be associated with the switch statement.
Given a switch statement, all of the following must be true or a compile-time error occurs:
Every case constant associated with the switch statement must be assignment compatible with the type of the switch statement’s Expression (§5.2).
If the type of the switch statement’s Expression is an enum type, then every case constant associated with the switch statement must be an enum constant of that type.
No two of the case constants associated with the switch statement have the same value.
No case constant associated with the switch statement is null .
At most one default label is associated with the switch statement.
The prohibition against using null as a case constant prevents code being written that can never be executed. If the switch statement’s Expression is of a reference type, that is, String or a boxed primitive type or an enum type, then an exception will be thrown will occur if the Expression evaluates to null at run time. In the judgment of the designers of the Java programming language, this is a better outcome than silently skipping the entire switch statement or choosing to execute the statements (if any) after the default label (if any).
A Java compiler is encouraged (but not required) to provide a warning if a switch on an enum-valued expression lacks a default label and lacks case labels for one or more of the enum’s constants. Such a switch will silently do nothing if the expression evaluates to one of the missing constants.
In C and C++ the body of a switch statement can be a statement and statements with case labels do not have to be immediately contained by that statement. Consider the simple loop:
where n is known to be positive. A trick known as Duff’s device can be used in C or C++ to unroll the loop, but this is not valid code in the Java programming language:
Fortunately, this trick does not seem to be widely known or used. Moreover, it is less needed nowadays; this sort of code transformation is properly in the province of state-of-the-art optimizing compilers.
When the switch statement is executed, first the Expression is evaluated. If the Expression evaluates to null , a NullPointerException is thrown and the entire switch statement completes abruptly for that reason. Otherwise, if the result is of a reference type, it is subject to unboxing conversion (§5.1.8).
If evaluation of the Expression or the subsequent unboxing conversion (if any) completes abruptly for some reason, the switch statement completes abruptly for the same reason.
Otherwise, execution continues by comparing the value of the Expression with each case constant, and there is a choice:
If one of the case constants is equal to the value of the expression, then we say that the case label matches . All statements after the matching case label in the switch block, if any, are executed in sequence.
If all these statements complete normally, or if there are no statements after the matching case label, then the entire switch statement completes normally.
If no case label matches but there is a default label, then all statements after the default label in the switch block, if any, are executed in sequence.
If all these statements complete normally, or if there are no statements after the default label, then the entire switch statement completes normally.
If no case label matches and there is no default label, then no further action is taken and the switch statement completes normally.
If any statement immediately contained by the Block body of the switch statement completes abruptly, it is handled as follows:
If execution of the Statement completes abruptly because of a break with no label, no further action is taken and the switch statement completes normally.
If execution of the Statement completes abruptly for any other reason, the switch statement completes abruptly for the same reason.
The case of abrupt completion because of a break with a label is handled by the general rule for labeled statements (§14.7).
Example 14.11-1. Fall-Through in the switch Statement
As in C and C++, execution of statements in a switch block «falls through labels.»
For example, the program:
contains a switch block in which the code for each case falls through into the code for the next case . As a result, the program prints:
If code is not to fall through case to case in this manner, then break statements should be used, as in this example:
This program prints:
14.12. The while Statement
The while statement executes an Expression and a Statement repeatedly until the value of the Expression is false .
The Expression must have type boolean or Boolean , or a compile-time error occurs.
A while statement is executed by first evaluating the Expression . If the result is of type Boolean , it is subject to unboxing conversion (§5.1.8).
If evaluation of the Expression or the subsequent unboxing conversion (if any) completes abruptly for some reason, the while statement completes abruptly for the same reason.
Otherwise, execution continues by making a choice based on the resulting value:
If the value is true , then the contained Statement is executed. Then there is a choice:
If execution of the Statement completes normally, then the entire while statement is executed again, beginning by re-evaluating the Expression .
If execution of the Statement completes abruptly, see §14.12.1.
If the (possibly unboxed) value of the Expression is false , no further action is taken and the while statement completes normally.
If the (possibly unboxed) value of the Expression is false the first time it is evaluated, then the Statement is not executed.
14.12.1. Abrupt Completion of while Statement
Abrupt completion of the contained Statement is handled in the following manner:
If execution of the Statement completes abruptly because of a break with no label, no further action is taken and the while statement completes normally.
If execution of the Statement completes abruptly because of a continue with no label, then the entire while statement is executed again.
If execution of the Statement completes abruptly because of a continue with label L , then there is a choice:
If the while statement has label L , then the entire while statement is executed again.
If the while statement does not have label L , the while statement completes abruptly because of a continue with label L .
If execution of the Statement completes abruptly for any other reason, the while statement completes abruptly for the same reason.
The case of abrupt completion because of a break with a label is handled by the general rule for labeled statements (§14.7).
14.13. The do Statement
The do statement executes a Statement and an Expression repeatedly until the value of the Expression is false .
The Expression must have type boolean or Boolean , or a compile-time error occurs.
A do statement is executed by first executing the Statement . Then there is a choice:
If execution of the Statement completes normally, then the Expression is evaluated. If the result is of type Boolean , it is subject to unboxing conversion (§5.1.8).
If evaluation of the Expression or the subsequent unboxing conversion (if any) completes abruptly for some reason, the do statement completes abruptly for the same reason.
Otherwise, there is a choice based on the resulting value:
If the value is true , then the entire do statement is executed again.
If the value is false , no further action is taken and the do statement completes normally.
If execution of the Statement completes abruptly, see §14.13.1.
Executing a do statement always executes the contained Statement at least once.
14.13.1. Abrupt Completion of do Statement
Abrupt completion of the contained Statement is handled in the following manner:
If execution of the Statement completes abruptly because of a break with no label, then no further action is taken and the do statement completes normally.
If execution of the Statement completes abruptly because of a continue with no label, then the Expression is evaluated. Then there is a choice based on the resulting value:
If the value is true , then the entire do statement is executed again.
If the value is false , no further action is taken and the do statement completes normally.
If execution of the Statement completes abruptly because of a continue with label L , then there is a choice:
If the do statement has label L , then the Expression is evaluated. Then there is a choice:
If the value of the Expression is true , then the entire do statement is executed again.
If the value of the Expression is false , no further action is taken and the do statement completes normally.
If the do statement does not have label L , the do statement completes abruptly because of a continue with label L .
If execution of the Statement completes abruptly for any other reason, the do statement completes abruptly for the same reason.
The case of abrupt completion because of a break with a label is handled by the general rule for labeled statements (§14.7).
Example 14.13-1. The do Statement
The following code is one possible implementation of the toHexString method of class Integer :
Because at least one digit must be generated, the do statement is an appropriate control structure.
14.14. The for Statement
The for statement has two forms:
The basic for statement.
The enhanced for statement
14.14.1. The basic for Statement
The basic for statement executes some initialization code, then executes an Expression , a Statement , and some update code repeatedly until the value of the Expression is false .
The Expression must have type boolean or Boolean , or a compile-time error occurs.
The scope and shadowing of a local variable declared in the ForInit part of a basic for statement is specified in §6.3 and §6.4.
14.14.1.1. Initialization of for Statement
A for statement is executed by first executing the ForInit code:
If the ForInit code is a list of statement expressions (§14.8), the expressions are evaluated in sequence from left to right; their values, if any, are discarded.
If evaluation of any expression completes abruptly for some reason, the for statement completes abruptly for the same reason; any ForInit statement expressions to the right of the one that completed abruptly are not evaluated.
If the ForInit code is a local variable declaration (§14.4), it is executed as if it were a local variable declaration statement appearing in a block.
If execution of the local variable declaration completes abruptly for any reason, the for statement completes abruptly for the same reason.
If the ForInit part is not present, no action is taken.
14.14.1.2. Iteration of for Statement
Next, a for iteration step is performed, as follows:
If the Expression is present, it is evaluated. If the result is of type Boolean , it is subject to unboxing conversion (§5.1.8).
If evaluation of the Expression or the subsequent unboxing conversion (if any) completes abruptly, the for statement completes abruptly for the same reason.
Otherwise, there is then a choice based on the presence or absence of the Expression and the resulting value if the Expression is present; see next bullet.
If the Expression is not present, or it is present and the value resulting from its evaluation (including any possible unboxing) is true , then the contained Statement is executed. Then there is a choice:
If execution of the Statement completes normally, then the following two steps are performed in sequence:
First, if the ForUpdate part is present, the expressions are evaluated in sequence from left to right; their values, if any, are discarded. If evaluation of any expression completes abruptly for some reason, the for statement completes abruptly for the same reason; any ForUpdate statement expressions to the right of the one that completed abruptly are not evaluated.
If the ForUpdate part is not present, no action is taken.
Second, another for iteration step is performed.
If execution of the Statement completes abruptly, see §14.14.1.3.
If the Expression is present and the value resulting from its evaluation (including any possible unboxing) is false , no further action is taken and the for statement completes normally.
If the (possibly unboxed) value of the Expression is false the first time it is evaluated, then the Statement is not executed.
If the Expression is not present, then the only way a for statement can complete normally is by use of a break statement.
14.14.1.3. Abrupt Completion of for Statement
Abrupt completion of the contained Statement is handled in the following manner:
If execution of the Statement completes abruptly because of a break with no label, no further action is taken and the for statement completes normally.
If execution of the Statement completes abruptly because of a continue with no label, then the following two steps are performed in sequence:
First, if the ForUpdate part is present, the expressions are evaluated in sequence from left to right; their values, if any, are discarded.
If the ForUpdate part is not present, no action is taken.
Second, another for iteration step is performed.
If execution of the Statement completes abruptly because of a continue with label L , then there is a choice:
If the for statement has label L , then the following two steps are performed in sequence:
First, if the ForUpdate part is present, the expressions are evaluated in sequence from left to right; their values, if any, are discarded.
If the ForUpdate is not present, no action is taken.
Second, another for iteration step is performed.
If the for statement does not have label L , the for statement completes abruptly because of a continue with label L .
If execution of the Statement completes abruptly for any other reason, the for statement completes abruptly for the same reason.
Note that the case of abrupt completion because of a break with a label is handled by the general rule for labeled statements (§14.7).
14.14.2. The enhanced for statement
The enhanced for statement has the form:
See §8.3 for UnannType . The following productions from §4.3, §8.4.1, and §8.3 are shown here for convenience:
The type of the Expression must be Iterable or an array type (§10.1), or a compile-time error occurs.
The declared type of the local variable in the header of the enhanced for statement is denoted by UnannType if no bracket pairs appear in UnannType and VariableDeclaratorId , and is specified by §10.2 otherwise.
The scope and shadowing of the local variable declared in the header of an enhanced for statement is specified in §6.3 and §6.4.
The meaning of the enhanced for statement is given by translation into a basic for statement, as follows:
If the type of Expression is a subtype of Iterable , then the translation is as follows.
If the type of Expression is a subtype of Iterable X > for some type argument X , then let I be the type java.util.Iterator X > ; otherwise, let I be the raw type java.util.Iterator .
The enhanced for statement is equivalent to a basic for statement of the form:
#i is an automatically generated identifier that is distinct from any other identifiers (automatically generated or otherwise) that are in scope (§6.3) at the point where the enhanced for statement occurs.
If the declared type of the local variable in the header of the enhanced for statement is a reference type, then TargetType is that declared type; otherwise, TargetType is the upper bound of the capture conversion (§5.1.10) of the type argument of I , or Object if I is raw.
For example, this code:
will be translated to:
Otherwise, the Expression necessarily has an array type, T [] .
Let L1 . Lm be the (possibly empty) sequence of labels immediately preceding the enhanced for statement.
The enhanced for statement is equivalent to a basic for statement of the form:
#a and #i are automatically generated identifiers that are distinct from any other identifiers (automatically generated or otherwise) that are in scope at the point where the enhanced for statement occurs.
TargetType is the declared type of the local variable in the header of the enhanced for statement.
Example 14.14-1. Enhanced for And Arrays
The following program, which calculates the sum of an integer array, shows how enhanced for works for arrays:
Example 14.14-2. Enhanced for And Unboxing Conversion
The following program combines the enhanced for statement with auto-unboxing to translate a histogram into a frequency table:
14.15. The break Statement
A break statement transfers control out of an enclosing statement.
A break statement with no label attempts to transfer control to the innermost enclosing switch , while , do , or for statement of the immediately enclosing method or initializer; this statement, which is called the break target , then immediately completes normally.
To be precise, a break statement with no label always completes abruptly, the reason being a break with no label.
If no switch , while , do , or for statement in the immediately enclosing method, constructor, or initializer contains the break statement, a compile-time error occurs.
A break statement with label Identifier attempts to transfer control to the enclosing labeled statement (§14.7) that has the same Identifier as its label; this statement, which is called the break target , then immediately completes normally. In this case, the break target need not be a switch , while , do , or for statement.
To be precise, a break statement with label Identifier always completes abruptly, the reason being a break with label Identifier .
A break statement must refer to a label within the immediately enclosing method, constructor, initializer, or lambda body. There are no non-local jumps. If no labeled statement with Identifier as its label in the immediately enclosing method, constructor, initializer, or lambda body contains the break statement, a compile-time error occurs.
It can be seen, then, that a break statement always completes abruptly.
The preceding descriptions say «attempts to transfer control» rather than just «transfers control» because if there are any try statements (§14.20) within the break target whose try blocks or catch clauses contain the break statement, then any finally clauses of those try statements are executed, in order, innermost to outermost, before control is transferred to the break target. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a break statement.
Example 14.15-1. The break Statement
In the following example, a mathematical graph is represented by an array of arrays. A graph consists of a set of nodes and a set of edges; each edge is an arrow that points from some node to some other node, or from a node to itself. In this example it is assumed that there are no redundant edges; that is, for any two nodes P and Q , where Q may be the same as P , there is at most one edge from P to Q .
Nodes are represented by integers, and there is an edge from node i to node edges[ i ][ j ] for every i and j for which the array reference edges[ i ][ j ] does not throw an ArrayIndexOutOfBoundsException .
The task of the method loseEdges , given integers i and j , is to construct a new graph by copying a given graph but omitting the edge from node i to node j , if any, and the edge from node j to node i , if any:
Note the use of two statement labels, edgelist and search , and the use of break statements. This allows the code that copies a list, omitting one edge, to be shared between two separate tests, the test for an edge from node i to node j , and the test for an edge from node j to node i .
14.16. The continue Statement
A continue statement may occur only in a while , do , or for statement; statements of these three kinds are called iteration statements . Control passes to the loop-continuation point of an iteration statement.
A continue statement with no label attempts to transfer control to the innermost enclosing while , do , or for statement of the immediately enclosing method, constructor, or initializer; this statement, which is called the continue target , then immediately ends the current iteration and begins a new one.
To be precise, such a continue statement always completes abruptly, the reason being a continue with no label.
If no while , do , or for statement of the immediately enclosing method, constructor, or initializer contains the continue statement, a compile-time error occurs.
A continue statement with label Identifier attempts to transfer control to the enclosing labeled statement (§14.7) that has the same Identifier as its label; that statement, which is called the continue target , then immediately ends the current iteration and begins a new one.
To be precise, a continue statement with label Identifier always completes abruptly, the reason being a continue with label Identifier .
The continue target must be a while , do , or for statement, or a compile-time error occurs.
A continue statement must refer to a label within the immediately enclosing method, constructor, initializer, or lambda body. There are no non-local jumps. If no labeled statement with Identifier as its label in the immediately enclosing method, constructor, initializer, or lambda body contains the continue statement, a compile-time error occurs.
It can be seen, then, that a continue statement always completes abruptly.
See the descriptions of the while statement (§14.12), do statement (§14.13), and for statement (§14.14) for a discussion of the handling of abrupt termination because of continue .
The preceding descriptions say «attempts to transfer control» rather than just «transfers control» because if there are any try statements (§14.20) within the continue target whose try blocks or catch clauses contain the continue statement, then any finally clauses of those try statements are executed, in order, innermost to outermost, before control is transferred to the continue target. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a continue statement.
Example 14.16-1. The continue Statement
In the Graph class in §14.15, one of the break statements is used to finish execution of the entire body of the outermost for loop. This break can be replaced by a continue if the for loop itself is labeled:
Which to use, if either, is largely a matter of programming style.
14.17. The return Statement
A return statement returns control to the invoker of a method (§8.4, §15.12) or constructor (§8.8, §15.9).
A return statement is contained in the innermost constructor, method, initializer, or lambda expression whose body encloses the return statement.
It is a compile-time error if a return statement is contained in an instance initializer or a static initializer (§8.6, §8.7).
A return statement with no Expression must be contained in one of the following, or a compile-time error occurs:
A method that is declared, using the keyword void , not to return a value (§8.4.5)
A lambda expression (§15.27)
A return statement with no Expression attempts to transfer control to the invoker of the method, constructor, or lambda body that contains it. To be precise, a return statement with no Expression always completes abruptly, the reason being a return with no value.
A return statement with an Expression must be contained in one of the following, or a compile-time error occurs:
A method that is declared to return a value
A lambda expression
The Expression must denote a variable or a value, or a compile-time error occurs.
When a return statement with an Expression appears in a method declaration, the Expression must be assignable (§5.2) to the declared return type of the method, or a compile-time error occurs.
A return statement with an Expression attempts to transfer control to the invoker of the method or lambda body that contains it; the value of the Expression becomes the value of the method invocation. More precisely, execution of such a return statement first evaluates the Expression . If the evaluation of the Expression completes abruptly for some reason, then the return statement completes abruptly for that reason. If evaluation of the Expression completes normally, producing a value V , then the return statement completes abruptly, the reason being a return with value V .
If the expression is of type float and is not FP-strict (§15.4), then the value may be an element of either the float value set or the float-extended-exponent value set (§4.2.3). If the expression is of type double and is not FP-strict, then the value may be an element of either the double value set or the double-extended-exponent value set.
It can be seen, then, that a return statement always completes abruptly.
The preceding descriptions say «attempts to transfer control» rather than just «transfers control» because if there are any try statements (§14.20) within the method or constructor whose try blocks or catch clauses contain the return statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.
14.18. The throw Statement
A throw statement causes an exception (§11 (Exceptions)) to be thrown. The result is an immediate transfer of control (§11.3) that may exit multiple statements and multiple constructor, instance initializer, static initializer and field initializer evaluations, and method invocations until a try statement (§14.20) is found that catches the thrown value. If no such try statement is found, then execution of the thread (§17 (Threads and Locks)) that executed the throw is terminated (§11.3) after invocation of the uncaughtException method for the thread group to which the thread belongs.
The Expression in a throw statement must either denote a variable or value of a reference type which is assignable (§5.2) to the type Throwable , or denote the null reference, or a compile-time error occurs.
The reference type of the Expression will always be a class type (since no interface types are assignable to Throwable ) which is not parameterized (since a subclass of Throwable cannot be generic (§8.1.2)).
At least one of the following three conditions must be true, or a compile-time error occurs:
The type of the Expression is an unchecked exception class (§11.1.1) or the null type (§4.1).
The throw statement is contained in the try block of a try statement (§14.20) and it is not the case that the try statement can throw an exception of the type of the Expression . (In this case we say the thrown value is caught by the try statement.)
The throw statement is contained in a method or constructor declaration and the type of the Expression is assignable (§5.2) to at least one type listed in the throws clause (§8.4.6, §8.8.5) of the declaration.
The exception types that a throw statement can throw are specified in §11.2.2.
A throw statement first evaluates the Expression . Then:
If evaluation of the Expression completes abruptly for some reason, then the throw completes abruptly for that reason.
If evaluation of the Expression completes normally, producing a non- null value V , then the throw statement completes abruptly, the reason being a throw with value V .
If evaluation of the Expression completes normally, producing a null value, then an instance V’ of class NullPointerException is created and thrown instead of null . The throw statement then completes abruptly, the reason being a throw with value V’ .
It can be seen, then, that a throw statement always completes abruptly.
If there are any enclosing try statements (§14.20) whose try blocks contain the throw statement, then any finally clauses of those try statements are executed as control is transferred outward, until the thrown value is caught. Note that abrupt completion of a finally clause can disrupt the transfer of control initiated by a throw statement.
If a throw statement is contained in a method declaration or a lambda expression, but its value is not caught by some try statement that contains it, then the invocation of the method completes abruptly because of the throw .
If a throw statement is contained in a constructor declaration, but its value is not caught by some try statement that contains it, then the class instance creation expression that invoked the constructor will complete abruptly because of the throw (§15.9.4).
If a throw statement is contained in a static initializer (§8.7), then a compile-time check (§11.2.3) ensures that either its value is always an unchecked exception or its value is always caught by some try statement that contains it. If at run time, despite this check, the value is not caught by some try statement that contains the throw statement, then the value is rethrown if it is an instance of class Error or one of its subclasses; otherwise, it is wrapped in an ExceptionInInitializerError object, which is then thrown (§12.4.2).
If a throw statement is contained in an instance initializer (§8.6), then a compile-time check (§11.2.3) ensures that either its value is always an unchecked exception or its value is always caught by some try statement that contains it, or the type of the thrown exception (or one of its superclasses) occurs in the throws clause of every constructor of the class.
By convention, user-declared throwable types should usually be declared to be subclasses of class Exception , which is a subclass of class Throwable (§11.1.1).
14.19. The synchronized Statement
A synchronized statement acquires a mutual-exclusion lock (§17.1) on behalf of the executing thread, executes a block, then releases the lock. While the executing thread owns the lock, no other thread may acquire the lock.
The type of Expression must be a reference type, or a compile-time error occurs.
A synchronized statement is executed by first evaluating the Expression . Then:
If evaluation of the Expression completes abruptly for some reason, then the synchronized statement completes abruptly for the same reason.
Otherwise, if the value of the Expression is null , a NullPointerException is thrown.
Otherwise, let the non- null value of the Expression be V . The executing thread locks the monitor associated with V . Then the Block is executed, and then there is a choice:
If execution of the Block completes normally, then the monitor is unlocked and the synchronized statement completes normally.
If execution of the Block completes abruptly for any reason, then the monitor is unlocked and the synchronized statement completes abruptly for the same reason.
The locks acquired by synchronized statements are the same as the locks that are acquired implicitly by synchronized methods (§8.4.3.6). A single thread may acquire a lock more than once.
Acquiring the lock associated with an object does not in itself prevent other threads from accessing fields of the object or invoking un- synchronized methods on the object. Other threads can also use synchronized methods or the synchronized statement in a conventional manner to achieve mutual exclusion.
Example 14.19-1. The synchronized Statement
This program produces the output:
Note that this program would deadlock if a single thread were not permitted to lock a monitor more than once.
14.20. The try statement
A try statement executes a block. If a value is thrown and the try statement has one or more catch clauses that can catch it, then control will be transferred to the first such catch clause. If the try statement has a finally clause, then another block of code is executed, no matter whether the try block completes normally or abruptly, and no matter whether a catch clause is first given control.
See §8.3 for UnannClassType . The following productions from §4.3, §8.3, and §8.4.1 are shown here for convenience:
The Block immediately after the keyword try is called the try block of the try statement.
The Block immediately after the keyword finally is called the finally block of the try statement.
A try statement may have catch clauses, also called exception handlers .
A catch clause declares exactly one parameter, which is called an exception parameter .
It is a compile-time error if final appears more than once as a modifier for an exception parameter declaration.
The scope and shadowing of an exception parameter is specified in §6.3 and §6.4.
An exception parameter may denote its type as either a single class type or a union of two or more class types (called alternatives ). The alternatives of a union are syntactically separated by | .
A catch clause whose exception parameter is denoted as a single class type is called a uni- catch clause .
A catch clause whose exception parameter is denoted as a union of types is called a multi- catch clause .
Each class type used in the denotation of the type of an exception parameter must be the class Throwable or a subclass of Throwable , or a compile-time error occurs.
It is a compile-time error if a type variable is used in the denotation of the type of an exception parameter.
It is a compile-time error if a union of types contains two alternatives Di and Dj ( i ≠ j ) where Di is a subtype of Dj (§4.10.2).
The declared type of an exception parameter that denotes its type with a single class type is that class type.
The declared type of an exception parameter that denotes its type as a union with alternatives D1 | D2 | . | Dn is lub( D1 , D2 , . Dn ).
An exception parameter of a multi- catch clause is implicitly declared final if it is not explicitly declared final .
It is a compile-time error if an exception parameter that is implicitly or explicitly declared final is assigned to within the body of the catch clause.
An exception parameter of a uni- catch clause is never implicitly declared final , but it may be explicitly declared final or be effectively final (§4.12.4).
An implicitly final exception parameter is final by virtue of its declaration, while an effectively final exception parameter is (as it were) final by virtue of how it is used. An exception parameter of a multi- catch clause is implicitly declared final , so will never occur as the left-hand operand of an assignment operator, but it is not considered effectively final.
If an exception parameter is effectively final (in a uni- catch clause) or implicitly final (in a multi- catch clause), then adding an explicit final modifier to its declaration will not introduce any compile-time errors. On the other hand, if the exception parameter of a uni- catch clause is explicitly declared final , then removing the final modifier may introduce compile-time errors because the exception parameter, now considered to be effectively final, can no longer longer be referenced by anonymous and local class declarations in the body of the catch clause. If there are no compile-time errors, it is possible to further change the program so that the exception parameter is re-assigned in the body of the catch clause and thus will no longer be considered effectively final.
The exception types that a try statement can throw are specified in §11.2.2.
The relationship of the exceptions thrown by the try block of a try statement and caught by the catch clauses (if any) of the try statement is specified in §11.2.3.
Exception handlers are considered in left-to-right order: the earliest possible catch clause accepts the exception, receiving as its argument the thrown exception object, as specified in §11.3.
A multi- catch clause can be thought of as a sequence of uni- catch clauses. That is, a catch clause where the type of the exception parameter is denoted as a union D1 | D2 | . | Dn is equivalent to a sequence of n catch clauses where the types of the exception parameters are class types D1 , D2 , . Dn respectively. In the Block of each of the n catch clauses, the declared type of the exception parameter is lub( D1 , D2 , . Dn ). For example, the following code:
is semantically equivalent to the following code:
where the multi- catch clause with two alternatives has been translated into two uni- catch clauses, one for each alternative. A Java compiler is neither required nor recommended to compile a multi- catch clause by duplicating code in this manner, since it is possible to represent the multi- catch clause in a class file without duplication.
A finally clause ensures that the finally block is executed after the try block and any catch block that might be executed, no matter how control leaves the try block or catch block. Handling of the finally block is rather complex, so the two cases of a try statement with and without a finally block are described separately (§14.20.1, §14.20.2).
A try statement is permitted to omit catch clauses and a finally clause if it is a try -with-resources statement (§14.20.3).
14.20.1. Execution of try — catch
A try statement without a finally block is executed by first executing the try block. Then there is a choice:
If execution of the try block completes normally, then no further action is taken and the try statement completes normally.
If execution of the try block completes abruptly because of a throw of a value V , then there is a choice:
If the run-time type of V is assignment compatible with (§5.2) a catchable exception class of any catch clause of the try statement, then the first (leftmost) such catch clause is selected. The value V is assigned to the parameter of the selected catch clause, and the Block of that catch clause is executed, and then there is a choice:
If that block completes normally, then the try statement completes normally.
If that block completes abruptly for any reason, then the try statement completes abruptly for the same reason.
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the try statement completes abruptly because of a throw of the value V .
If execution of the try block completes abruptly for any other reason, then the try statement completes abruptly for the same reason.
Example 14.20.1-1. Catching An Exception
Here, the exception BlewIt is thrown by the method blowUp . The try — catch statement in the body of main has two catch clauses. The run-time type of the exception is BlewIt which is not assignable to a variable of type RuntimeException , but is assignable to a variable of type BlewIt , so the output of the example is:
14.20.2. Execution of try — finally and try — catch — finally
A try statement with a finally block is executed by first executing the try block. Then there is a choice:
If execution of the try block completes normally, then the finally block is executed, and then there is a choice:
If the finally block completes normally, then the try statement completes normally.
If the finally block completes abruptly for reason S , then the try statement completes abruptly for reason S .
If execution of the try block completes abruptly because of a throw of a value V , then there is a choice:
If the run-time type of V is assignment compatible with a catchable exception class of any catch clause of the try statement, then the first (leftmost) such catch clause is selected. The value V is assigned to the parameter of the selected catch clause, and the Block of that catch clause is executed. Then there is a choice:
If the catch block completes normally, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes normally.
If the finally block completes abruptly for any reason, then the try statement completes abruptly for the same reason.
If the catch block completes abruptly for reason R , then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R .
If the finally block completes abruptly for reason S , then the try statement completes abruptly for reason S (and reason R is discarded).
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V .
If the finally block completes abruptly for reason S , then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).
If execution of the try block completes abruptly for any other reason R , then the finally block is executed, and then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R .
If the finally block completes abruptly for reason S , then the try statement completes abruptly for reason S (and reason R is discarded).
Example 14.20.2-1. Handling An Uncaught Exception With finally
This program produces the output:
The NullPointerException (which is a kind of RuntimeException ) that is thrown by method blowUp is not caught by the try statement in main , because a NullPointerException is not assignable to a variable of type BlewIt . This causes the finally clause to execute, after which the thread executing main , which is the only thread of the test program, terminates because of an uncaught exception, which typically results in printing the exception name and a simple backtrace. However, a backtrace is not required by this specification.
The problem with mandating a backtrace is that an exception can be created at one point in the program and thrown at a later one. It is prohibitively expensive to store a stack trace in an exception unless it is actually thrown (in which case the trace may be generated while unwinding the stack). Hence we do not mandate a back trace in every exception.
14.20.3. try -with-resources
A try -with-resources statement is parameterized with variables (known as resources ) that are initialized before execution of the try block and closed automatically, in the reverse order from which they were initialized, after execution of the try block. catch clauses and a finally clause are often unnecessary when resources are closed automatically.