Movatterモバイル変換


[0]ホーム

URL:


Oracle Logo

Java SE >Java SE Specifications >Java Language Specification

Chapter 14. Blocks and Statements
Prev   Next

Chapter 14. Blocks and Statements

Table of Contents

14.1. Normal and Abrupt Completion of Statements
14.2. Blocks
14.3. Local Class Declarations
14.4. Local Variable Declaration Statements
14.4.1. Local Variable Declarators and Types
14.4.2. Execution of Local Variable Declarations
14.5. Statements
14.6. The Empty Statement
14.7. Labeled Statements
14.8. Expression Statements
14.9. Theif Statement
14.9.1. Theif-then Statement
14.9.2. Theif-then-else Statement
14.10. Theassert Statement
14.11. Theswitch Statement
14.12. Thewhile Statement
14.12.1. Abrupt Completion ofwhile Statement
14.13. Thedo Statement
14.13.1. Abrupt Completion ofdo Statement
14.14. Thefor Statement
14.14.1. The basicfor Statement
14.14.1.1. Initialization offor Statement
14.14.1.2. Iteration offor Statement
14.14.1.3. Abrupt Completion offor Statement
14.14.2. The enhancedfor statement
14.15. Thebreak Statement
14.16. Thecontinue Statement
14.17. Thereturn Statement
14.18. Thethrow Statement
14.19. Thesynchronized Statement
14.20. Thetry statement
14.20.1. Execution oftry-catch
14.20.2. Execution oftry-finally andtry-catch-finally
14.20.3.try-with-resources
14.20.3.1. Basictry-with-resources
14.20.3.2. Extendedtry-with-resources
14.21. Unreachable Statements

The sequence of execution of a program is controlled bystatements, which are executed for their effect and do not have values.

Some statementscontain other statements as part of their structure; such other statements are substatements of the statement. We say that statementSimmediately contains statementU if there is no statementT different fromS andU such thatS containsT andT containsU. 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 bereachable 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 tocomplete normally. However, certain events may prevent a statement from completing normally:

  • Thebreak (§14.15),continue (§14.16), andreturn (§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 explicitthrow (§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 tocomplete abruptly.

An abrupt completion always has an associatedreason, which is one of the following:

  • Abreak with no label

  • Abreak with a given label

  • Acontinue with no label

  • Acontinue with a given label

  • Areturn with no value

  • Areturn with a given value

  • Athrow 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 athrow 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

Ablock is a sequence of statements, local class declarations, and local variable declaration statements within braces.

Block:
{ [BlockStatements]}
BlockStatements:
BlockStatement {BlockStatement}
BlockStatement:
LocalVariableDeclarationStatement
ClassDeclaration
Statement

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

Alocal 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 modifierspublic,protected, orprivate (§6.6), or the modifierstatic (§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:

class Global {    class Cyclic {}    void foo() {        new Cyclic(); // create a Global.Cyclic        class Cyclic extends Cyclic {} // circular definition        {            class Local {}            {                class Local {} // compile-time error            }            class Local {} // compile-time error            class AnotherLocal {                void bar() {                    class Local {} // ok                }            }        }        class Local {} // ok, not in scope of prior Local    }}

The first statement of methodfoo creates an instance of the member classGlobal.Cyclic rather than an instance of the local classCyclic, 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 classCyclic is indeed cyclic because it extends itself rather thanGlobal.Cyclic. Consequently, the declaration of the local classCyclic 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 ofLocal result in compile-time errors. However,Local can be redeclared in the context of another, more deeply nested, class such asAnotherLocal.

The final declaration ofLocal is legal, since it occurs outside the scope of any prior declaration ofLocal.


14.4. Local Variable Declaration Statements

Alocal variable declaration statement declares one or more local variable names.

LocalVariableDeclarationStatement:
LocalVariableDeclaration;
LocalVariableDeclaration:
{VariableModifier}UnannTypeVariableDeclaratorList

See§8.3 forUnannType. The following productions from§4.3,§8.4.1, and§8.3 are shown here for convenience:

VariableModifier:
(one of)
Annotationfinal
VariableDeclaratorList:
VariableDeclarator:
VariableDeclaratorId:
Dims:
VariableInitializer:

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 afor statement (§14.14) ortry-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 iffinal appears more than once as a modifier for a local variable declaration.

14.4.1. Local Variable Declarators and Types

Eachdeclarator in a local variable declaration declares one local variable, whose name is theIdentifier that appears in the declarator.

If the optional keywordfinal 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 byUnannType if no bracket pairs appear inUnannType andVariableDeclaratorId, and is specified by§10.2 otherwise.

A local variable of typefloat always contains a value that is an element of the float value set (§4.2.3); similarly, a local variable of typedouble always contains a value that is an element of the double value set. It is not permitted for a local variable of typefloat 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 typedouble 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++, theif statement of the Java programming language suffers from the so-called "danglingelse problem," illustrated by this misleadingly formatted example:

if (door.isOpen())    if (resident.isVisible())        resident.greet("Hello!");else door.bell.ring();  // A "dangling else"

The problem is that both the outerif statement and the innerif statement might conceivably own theelse clause. In this example, one might surmise that the programmer intended theelse clause to belong to the outerif statement.

The Java programming language, like C and C++ and many programming languages before them, arbitrarily decrees that anelse clause belongs to the innermostif to which it might possibly belong. This rule is captured by the following grammar:

Statement:
StatementWithoutTrailingSubstatement
LabeledStatement
IfThenStatement
IfThenElseStatement
WhileStatement
ForStatement
StatementNoShortIf:
StatementWithoutTrailingSubstatement
LabeledStatementNoShortIf
IfThenElseStatementNoShortIf
WhileStatementNoShortIf
ForStatementNoShortIf
StatementWithoutTrailingSubstatement:
Block
EmptyStatement
ExpressionStatement
AssertStatement
SwitchStatement
DoStatement
BreakStatement
ContinueStatement
ReturnStatement
SynchronizedStatement
ThrowStatement
TryStatement

The following productions from§14.9 are shown here for convenience:

IfThenStatement:
IfThenElseStatement:
IfThenElseStatementNoShortIf:

Statements are thus grammatically divided into two categories: those that might end in anif statement that has noelse clause (a "shortif statement") and those that definitely do not.

Only statements that definitely do not end in a shortif statement may appear as an immediate substatement before the keywordelse in anif statement that does have anelse clause.

This simple rule prevents the "danglingelse" problem. The execution behavior of a statement with the "no shortif" restriction is identical to the execution behavior of the same kind of statement without the "no shortif" restriction; the distinction is drawn purely to resolve the syntactic difficulty.

14.6. The Empty Statement

An empty statement does nothing.

EmptyStatement:
;

Execution of an empty statement always completes normally.

14.7. Labeled Statements

Statements may havelabel prefixes.

LabeledStatement:
Identifier:Statement
LabeledStatementNoShortIf:
Identifier:StatementNoShortIf

TheIdentifier is declared to be the label of the immediately containedStatement.

Unlike C and C++, the Java programming language has nogoto statement; identifier statement labels are used withbreak orcontinue statements (§14.15,§14.16) appearing anywhere within the labeled statement.

The scope of a label of a labeled statement is the immediately containedStatement.

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 containedStatement.

If the statement is labeled by anIdentifier and the containedStatement completes abruptly because of abreak with the sameIdentifier, then the labeled statement completes normally. In all other cases of abrupt completion of theStatement, 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 classString and its methodindexOf, where the label was originally calledtest. Changing the label to have the same name as the local variablei does not obscure the label in the scope of the declaration ofi. Thus, the code is valid.

class Test {    char[] value;    int offset, count;    int indexOf(TestString str, int fromIndex) {        char[] v1 = value, v2 = str.value;        int max = offset + (count - str.count);        int start = offset + ((fromIndex < 0) ? 0 : fromIndex);    i:        for (int i = start; i <= max; i++) {            int n = str.count, j = i, k = str.offset;            while (n-- != 0) {                if (v1[j++] != v2[k++])                    continue i;            }             return i - offset;        }        return -1;    }}

The identifiermax could also have been used as the statement label; the label would not obscure the local variablemax within the labeled statement.


14.8. Expression Statements

Certain kinds of expressions may be used as statements by following them with semicolons.

ExpressionStatement:
StatementExpression;
StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression

Anexpression 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):

System.out.println("Hello world");  // OK

but it is not legal to use a parenthesized expression (§15.8.5):

(System.out.println("Hello world"));  // illegal

Note that the Java programming language does not allow a "cast tovoid" -void is not a type - so the traditional C trick of writing an expression statement such as:

(void)... ;  // incorrect!

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 avoid 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. Theif Statement

Theif statement allows conditional execution of a statement or a conditional choice of two statements, executing one or the other but not both.

IfThenStatement:
if(Expression)Statement
IfThenElseStatement:
if(Expression)StatementNoShortIfelseStatement
IfThenElseStatementNoShortIf:
if(Expression)StatementNoShortIfelseStatementNoShortIf

TheExpression must have typeboolean orBoolean, or a compile-time error occurs.

14.9.1. Theif-then Statement

Anif-then statement is executed by first evaluating theExpression. If the result is of typeBoolean, it is subject to unboxing conversion (§5.1.8).

If evaluation of theExpression or the subsequent unboxing conversion (if any) completes abruptly for some reason, theif-then statement completes abruptly for the same reason.

Otherwise, execution continues by making a choice based on the resulting value:

  • If the value istrue, then the containedStatement is executed; theif-then statement completes normally if and only if execution of theStatement completes normally.

  • If the value isfalse, no further action is taken and theif-then statement completes normally.

14.9.2. Theif-then-else Statement

Anif-then-else statement is executed by first evaluating theExpression. If the result is of typeBoolean, it is subject to unboxing conversion (§5.1.8).

If evaluation of theExpression or the subsequent unboxing conversion (if any) completes abruptly for some reason, then theif-then-else statement completes abruptly for the same reason.

Otherwise, execution continues by making a choice based on the resulting value:

  • If the value istrue, then the first containedStatement (the one before theelse keyword) is executed; theif-then-else statement completes normally if and only if execution of that statement completes normally.

  • If the value isfalse, then the second containedStatement (the one after theelse keyword) is executed; theif-then-else statement completes normally if and only if execution of that statement completes normally.

14.10. Theassert Statement

Anassertion is anassert statement containing a boolean expression. An assertion is eitherenabled ordisabled. If an assertion is enabled, execution of the assertion causes evaluation of the boolean expression and an error is reported if the expression evaluates tofalse. If the assertion is disabled, execution of the assertion has no effect whatsoever.

AssertStatement:
assertExpression;
assertExpression:Expression;

To ease the presentation, the firstExpression in both forms of theassert statement is referred to asExpression1. In the second form of theassert statement, the secondExpression is referred to asExpression2.

It is a compile-time error ifExpression1 does not have typeboolean orBoolean.

In the second form of theassert statement, it is a compile-time error ifExpression2 is void (§15.1).

Anassert 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 theassert 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.

Anassert 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:

public class Foo {    public static void main(String[] args) {        Baz.testAsserts();         // Will execute after Baz is initialized.    }}class Bar {    static {        Baz.testAsserts();         // Will execute before Baz is initialized!    }}class Baz extends Bar {    static void testAsserts() {        boolean enabled = false;        assert  enabled = true;        System.out.println("Asserts " +    (enabled ? "enabled" : "disabled"));    }}

InvokingBaz.testAsserts() causesBaz to be initialized. Before this can happen,Bar must be initialized.Bar's static initializer again invokesBaz.testAsserts(). Because initialization ofBaz is already in progress by the current thread, the second invocation executes immediately, thoughBaz is not initialized (§12.4.2).

Because of the rule above, if the program above is executed without enabling assertions, it must print:

Asserts enabledAsserts disabled

A disabledassert statement does nothing. In particular, neitherExpression1 norExpression2 (if it is present) are evaluated. Execution of a disabledassert statement always completes normally.

An enabledassert statement is executed by first evaluatingExpression1. If the result is of typeBoolean, it is subject to unboxing conversion (§5.1.8).

If evaluation ofExpression1 or the subsequent unboxing conversion (if any) completes abruptly for some reason, theassert statement completes abruptly for the same reason.

Otherwise, execution continues by making a choice based on the value ofExpression1:

  • If the value istrue, no further action is taken and theassert statement completes normally.

  • If the value isfalse, the execution behavior depends on whetherExpression2 is present:

    • IfExpression2 is present, it is evaluated. Then:

      • If the evaluation completes abruptly for some reason, theassert statement completes abruptly for the same reason.

      • If the evaluation completes normally, anAssertionError instance whose "detail message" is the resulting value ofExpression2 is created. Then:

        • If the instance creation completes abruptly for some reason, theassert statement completes abruptly for the same reason.

        • If the instance creation completes normally, theassert statement completes abruptly by throwing the newly createdAssertionError object.

    • IfExpression2 is not present, anAssertionError instance with no "detail message" is created. Then:

      • If the instance creation completes abruptly for some reason, theassert statement completes abruptly for the same reason.

      • If the instance creation completes normally, theassert statement completes abruptly by throwing the newly createdAssertionError 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 inpublic 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 asIllegalArgumentException,ArrayIndexOutOfBoundsException, orNullPointerException). An assertion failure will not throw an appropriate exception. Again, it is not illegal to use assertions for argument checking onpublic methods, but it is generally inappropriate. It is intended thatAssertionError never be caught, but it is possible to do so, thus the rules fortry statements should treat assertions appearing in atry block similarly to the current treatment ofthrow statements.

14.11. Theswitch Statement

Theswitch statement transfers control to one of several statements depending on the value of an expression.

SwitchStatement:
switch(Expression)SwitchBlock
SwitchBlock:
{ {SwitchBlockStatementGroup} {SwitchLabel}}
SwitchBlockStatementGroup:
SwitchLabelsBlockStatements
SwitchLabels:
SwitchLabel {SwitchLabel}
SwitchLabel:
caseConstantExpression:
caseEnumConstantName:
default:
EnumConstantName:
Identifier

The type of theExpression must bechar,byte,short,int,Character,Byte,Short,Integer,String, or an enum type (§8.9), or a compile-time error occurs.

The body of aswitch statement is known as aswitch block. Any statement immediately contained by the switch block may be labeled with one or moreswitch labels, which arecase ordefault labels. Everycase label has acase constant, which is either a constant expression or the name of an enum constant. Switch labels and theircase constants are said to beassociated with theswitch statement.

Given aswitch statement, all of the following must be true or a compile-time error occurs:

  • Everycase constant associated with theswitch statement must be assignment compatible with the type of theswitch statement'sExpression (§5.2).

  • If the type of theswitch statement'sExpression is an enum type, then everycase constant associated with theswitch statement must be an enum constant of that type.

  • No two of thecase constants associated with theswitch statement have the same value.

  • Nocase constant associated with theswitch statement isnull.

  • At most onedefault label is associated with theswitch statement.

The prohibition against usingnull as acase constant prevents code being written that can never be executed. If theswitch statement'sExpression 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 theExpression evaluates tonull at run time. In the judgment of the designers of the Java programming language, this is a better outcome than silently skipping the entireswitch statement or choosing to execute the statements (if any) after thedefault label (if any).

A Java compiler is encouraged (but not required) to provide a warning if aswitch on an enum-valued expression lacks adefault label and lackscase labels for one or more of the enum's constants. Such aswitch will silently do nothing if the expression evaluates to one of the missing constants.

In C and C++ the body of aswitch statement can be a statement and statements withcase labels do not have to be immediately contained by that statement. Consider the simple loop:

for (i = 0; i < n; ++i) foo();

wheren is known to be positive. A trick known asDuff's device can be used in C or C++ to unroll the loop, but this is not valid code in the Java programming language:

int q = (n+7)/8;switch (n%8) {    case 0: do { foo();    // Great C hack, Tom,    case 7:      foo();    // but it's not valid here.    case 6:      foo();    case 5:      foo();    case 4:      foo();    case 3:      foo();    case 2:      foo();    case 1:      foo();            } while (--q > 0);}

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 theswitch statement is executed, first theExpression is evaluated. If theExpression evaluates tonull, aNullPointerException is thrown and the entireswitch 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 theExpression or the subsequent unboxing conversion (if any) completes abruptly for some reason, theswitch statement completes abruptly for the same reason.

Otherwise, execution continues by comparing the value of theExpression with eachcase constant, and there is a choice:

  • If one of thecase constants is equal to the value of the expression, then we say that thecase labelmatches. All statements after the matchingcase label in theswitch block, if any, are executed in sequence.

    If all these statements complete normally, or if there are no statements after the matchingcase label, then the entireswitch statement completes normally.

  • If nocase label matches but there is adefault label, then all statements after thedefault label in theswitch block, if any, are executed in sequence.

    If all these statements complete normally, or if there are no statements after thedefault label, then the entireswitch statement completes normally.

  • If nocase label matches and there is nodefault label, then no further action is taken and theswitch statement completes normally.

If any statement immediately contained by theBlock body of theswitch statement completes abruptly, it is handled as follows:

  • If execution of theStatement completes abruptly because of abreak with no label, no further action is taken and theswitch statement completes normally.

  • If execution of theStatement completes abruptly for any other reason, theswitch statement completes abruptly for the same reason.

    The case of abrupt completion because of abreak with a label is handled by the general rule for labeled statements (§14.7).

Example 14.11-1. Fall-Through in theswitch Statement

As in C and C++, execution of statements in aswitch block "falls through labels."

For example, the program:

class TooMany {    static void howMany(int k) {        switch (k) {            case 1: System.out.print("one ");            case 2: System.out.print("too ");            case 3: System.out.println("many");        }    }    public static void main(String[] args) {        howMany(3);        howMany(2);        howMany(1);    }}

contains aswitch block in which the code for eachcase falls through into the code for the nextcase. As a result, the program prints:

manytoo manyone too many

If code is not to fall throughcase tocase in this manner, thenbreak statements should be used, as in this example:

class TwoMany {    static void howMany(int k) {        switch (k) {            case 1: System.out.println("one");                    break;  // exit the switch            case 2: System.out.println("two");                    break;  // exit the switch            case 3: System.out.println("many");                    break;  // not needed, but good style        }    }    public static void main(String[] args) {        howMany(1);        howMany(2);        howMany(3);    }}

This program prints:

onetwomany

14.12. Thewhile Statement

Thewhile statement executes anExpression and aStatement repeatedly until the value of theExpression isfalse.

WhileStatement:
while(Expression)Statement
WhileStatementNoShortIf:
while(Expression)StatementNoShortIf

TheExpression must have typeboolean orBoolean, or a compile-time error occurs.

Awhile statement is executed by first evaluating theExpression. If the result is of typeBoolean, it is subject to unboxing conversion (§5.1.8).

If evaluation of theExpression or the subsequent unboxing conversion (if any) completes abruptly for some reason, thewhile statement completes abruptly for the same reason.

Otherwise, execution continues by making a choice based on the resulting value:

  • If the value istrue, then the containedStatement is executed. Then there is a choice:

    • If execution of theStatement completes normally, then the entirewhile statement is executed again, beginning by re-evaluating theExpression.

    • If execution of theStatement completes abruptly, see§14.12.1.

  • If the (possibly unboxed) value of theExpression isfalse, no further action is taken and thewhile statement completes normally.

    If the (possibly unboxed) value of theExpression isfalse the first time it is evaluated, then theStatement is not executed.

14.12.1. Abrupt Completion ofwhile Statement

Abrupt completion of the containedStatement is handled in the following manner:

  • If execution of theStatement completes abruptly because of abreak with no label, no further action is taken and thewhile statement completes normally.

  • If execution of theStatement completes abruptly because of acontinue with no label, then the entirewhile statement is executed again.

  • If execution of theStatement completes abruptly because of acontinue with labelL, then there is a choice:

    • If thewhile statement has labelL, then the entirewhile statement is executed again.

    • If thewhile statement does not have labelL, thewhile statement completes abruptly because of acontinue with labelL.

  • If execution of theStatement completes abruptly for any other reason, thewhile statement completes abruptly for the same reason.

    The case of abrupt completion because of abreak with a label is handled by the general rule for labeled statements (§14.7).

14.13. Thedo Statement

Thedo statement executes aStatement and anExpression repeatedly until the value of theExpression isfalse.

DoStatement:
doStatementwhile(Expression);

TheExpression must have typeboolean orBoolean, or a compile-time error occurs.

Ado statement is executed by first executing theStatement. Then there is a choice:

  • If execution of theStatement completes normally, then theExpression is evaluated. If the result is of typeBoolean, it is subject to unboxing conversion (§5.1.8).

    If evaluation of theExpression or the subsequent unboxing conversion (if any) completes abruptly for some reason, thedo statement completes abruptly for the same reason.

    Otherwise, there is a choice based on the resulting value:

    • If the value istrue, then the entiredo statement is executed again.

    • If the value isfalse, no further action is taken and thedo statement completes normally.

  • If execution of theStatement completes abruptly, see§14.13.1.

Executing ado statement always executes the containedStatement at least once.

14.13.1. Abrupt Completion ofdo Statement

Abrupt completion of the containedStatement is handled in the following manner:

  • If execution of theStatement completes abruptly because of abreak with no label, then no further action is taken and thedo statement completes normally.

  • If execution of theStatement completes abruptly because of acontinue with no label, then theExpression is evaluated. Then there is a choice based on the resulting value:

    • If the value istrue, then the entiredo statement is executed again.

    • If the value isfalse, no further action is taken and thedo statement completes normally.

  • If execution of theStatement completes abruptly because of acontinue with labelL, then there is a choice:

    • If thedo statement has labelL, then theExpression is evaluated. Then there is a choice:

      • If the value of theExpression istrue, then the entiredo statement is executed again.

      • If the value of theExpression isfalse, no further action is taken and thedo statement completes normally.

    • If thedo statement does not have labelL, thedo statement completes abruptly because of acontinue with labelL.

  • If execution of theStatement completes abruptly for any other reason, thedo statement completes abruptly for the same reason.

    The case of abrupt completion because of abreak with a label is handled by the general rule for labeled statements (§14.7).

Example 14.13-1. Thedo Statement

The following code is one possible implementation of thetoHexString method of classInteger:

public static String toHexString(int i) {    StringBuffer buf = new StringBuffer(8);    do {        buf.append(Character.forDigit(i & 0xF, 16));        i >>>= 4;    } while (i != 0);    return buf.reverse().toString();}

Because at least one digit must be generated, thedo statement is an appropriate control structure.


14.14. Thefor Statement

Thefor statement has two forms:

  • The basicfor statement.

  • The enhancedfor statement

ForStatement:
BasicForStatement
EnhancedForStatement
ForStatementNoShortIf:
BasicForStatementNoShortIf
EnhancedForStatementNoShortIf

14.14.1. The basicfor Statement

The basicfor statement executes some initialization code, then executes anExpression, aStatement, and some update code repeatedly until the value of theExpression isfalse.

BasicForStatement:
BasicForStatementNoShortIf:
ForInit:
ForUpdate:
StatementExpressionList:

TheExpression must have typeboolean orBoolean, or a compile-time error occurs.

The scope and shadowing of a local variable declared in theForInit part of a basicfor statement is specified in§6.3 and§6.4.

14.14.1.1. Initialization offor Statement

Afor statement is executed by first executing theForInit code:

  • If theForInit 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, thefor statement completes abruptly for the same reason; anyForInit statement expressions to the right of the one that completed abruptly are not evaluated.

  • If theForInit 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, thefor statement completes abruptly for the same reason.

  • If theForInit part is not present, no action is taken.

14.14.1.2. Iteration offor Statement

Next, afor iteration step is performed, as follows:

  • If theExpression is present, it is evaluated. If the result is of typeBoolean, it is subject to unboxing conversion (§5.1.8).

    If evaluation of theExpression or the subsequent unboxing conversion (if any) completes abruptly, thefor statement completes abruptly for the same reason.

    Otherwise, there is then a choice based on the presence or absence of theExpression and the resulting value if theExpression is present; see next bullet.

  • If theExpression is not present, or it is present and the value resulting from its evaluation (including any possible unboxing) istrue, then the containedStatement is executed. Then there is a choice:

    • If execution of theStatement completes normally, then the following two steps are performed in sequence:

      1. First, if theForUpdate 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, thefor statement completes abruptly for the same reason; anyForUpdate statement expressions to the right of the one that completed abruptly are not evaluated.

        If theForUpdate part is not present, no action is taken.

      2. Second, anotherfor iteration step is performed.

    • If execution of theStatement completes abruptly, see§14.14.1.3.

  • If theExpression is present and the value resulting from its evaluation (including any possible unboxing) isfalse, no further action is taken and thefor statement completes normally.

    If the (possibly unboxed) value of theExpression isfalse the first time it is evaluated, then theStatement is not executed.

If theExpression is not present, then the only way afor statement can complete normally is by use of abreak statement.

14.14.1.3. Abrupt Completion offor Statement

Abrupt completion of the containedStatement is handled in the following manner:

  • If execution of theStatement completes abruptly because of abreak with no label, no further action is taken and thefor statement completes normally.

  • If execution of theStatement completes abruptly because of acontinue with no label, then the following two steps are performed in sequence:

    1. First, if theForUpdate part is present, the expressions are evaluated in sequence from left to right; their values, if any, are discarded.

      If theForUpdate part is not present, no action is taken.

    2. Second, anotherfor iteration step is performed.

  • If execution of theStatement completes abruptly because of acontinue with labelL, then there is a choice:

    • If thefor statement has labelL, then the following two steps are performed in sequence:

      1. First, if theForUpdate part is present, the expressions are evaluated in sequence from left to right; their values, if any, are discarded.

        If theForUpdate is not present, no action is taken.

      2. Second, anotherfor iteration step is performed.

    • If thefor statement does not have labelL, thefor statement completes abruptly because of acontinue with labelL.

  • If execution of theStatement completes abruptly for any other reason, thefor statement completes abruptly for the same reason.

    Note that the case of abrupt completion because of abreak with a label is handled by the general rule for labeled statements (§14.7).

14.14.2. The enhancedfor statement

The enhancedfor statement has the form:

EnhancedForStatement:
EnhancedForStatementNoShortIf:

See§8.3 forUnannType. The following productions from§4.3,§8.4.1, and§8.3 are shown here for convenience:

VariableModifier:
(one of)
Annotationfinal
VariableDeclaratorId:
Dims:

The type of theExpression must beIterable or an array type (§10.1), or a compile-time error occurs.

The declared type of the local variable in the header of the enhancedfor statement is denoted byUnannType if no bracket pairs appear inUnannType andVariableDeclaratorId, and is specified by§10.2 otherwise.

The scope and shadowing of the local variable declared in the header of an enhancedfor statement is specified in§6.3 and§6.4.

The meaning of the enhancedfor statement is given by translation into a basicfor statement, as follows:

  • If the type ofExpression is a subtype ofIterable, then the translation is as follows.

    If the type ofExpression is a subtype ofIterable<X> for some type argumentX, then letI be the typejava.util.Iterator<X>; otherwise, letI be the raw typejava.util.Iterator.

    The enhancedfor statement is equivalent to a basicfor statement of the form:

    for (I #i =Expression.iterator(); #i.hasNext(); ) {{VariableModifier} TargetType Identifier =        (TargetType) #i.next();Statement}

    #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 enhancedfor statement occurs.

    If the declared type of the local variable in the header of the enhancedfor statement is a reference type, thenTargetType is that declared type; otherwise,TargetType is the upper bound of the capture conversion (§5.1.10) of the type argument ofI, orObject ifI is raw.

    For example, this code:

    List<? extends Integer> l = ...for (float i : l) ...

    will be translated to:

    for (Iterator<Integer> #i = l.iterator(); #i.hasNext(); ) {    float #i0 = (Integer)#i.next();    ...
  • Otherwise, theExpression necessarily has an array type,T[].

    LetL1 ...Lm be the (possibly empty) sequence of labels immediately preceding the enhancedfor statement.

    The enhancedfor statement is equivalent to a basicfor statement of the form:

    T[] #a =Expression;L1:L2: ...Lm:for (int #i = 0; #i < #a.length; #i++) {{VariableModifier} TargetType Identifier = #a[#i];Statement}

    #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 enhancedfor statement occurs.

    TargetType is the declared type of the local variable in the header of the enhancedfor statement.

Example 14.14-1. Enhancedfor And Arrays

The following program, which calculates the sum of an integer array, shows how enhancedfor works for arrays:

int sum(int[] a) {    int sum = 0;    for (int i : a) sum += i;    return sum;}

Example 14.14-2. Enhancedfor And Unboxing Conversion

The following program combines the enhancedfor statement with auto-unboxing to translate a histogram into a frequency table:

Map<String, Integer> histogram = ...;double total = 0;for (int i : histogram.values())    total += i;for (Map.Entry<String, Integer> e : histogram.entrySet())    System.out.println(e.getKey() + " " + e.getValue() / total);}

14.15. Thebreak Statement

Abreak statement transfers control out of an enclosing statement.

BreakStatement:
break [Identifier];

Abreak statement with no label attempts to transfer control to the innermost enclosingswitch,while,do, orfor statement of the immediately enclosing method or initializer; this statement, which is called thebreak target, then immediately completes normally.

To be precise, abreak statement with no label always completes abruptly, the reason being abreak with no label.

If noswitch,while,do, orfor statement in the immediately enclosing method, constructor, or initializer contains thebreak statement, a compile-time error occurs.

Abreak statement with labelIdentifier attempts to transfer control to the enclosing labeled statement (§14.7) that has the sameIdentifier as its label; this statement, which is called thebreak target, then immediately completes normally. In this case, the break target need not be aswitch,while,do, orfor statement.

To be precise, abreak statement with labelIdentifier always completes abruptly, the reason being abreak with labelIdentifier.

Abreak 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 withIdentifier as its label in the immediately enclosing method, constructor, initializer, or lambda body contains thebreak statement, a compile-time error occurs.

It can be seen, then, that abreak statement always completes abruptly.

The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are anytry statements (§14.20) within the break target whosetry blocks orcatch clauses contain thebreak statement, then anyfinally clauses of thosetry statements are executed, in order, innermost to outermost, before control is transferred to the break target. Abrupt completion of afinally clause can disrupt the transfer of control initiated by abreak statement.

Example 14.15-1. Thebreak 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 nodesP andQ, whereQ may be the same asP, there is at most one edge fromP toQ.

Nodes are represented by integers, and there is an edge from nodei to nodeedges[i][j] for everyi andj for which the array referenceedges[i][j] does not throw anArrayIndexOutOfBoundsException.

The task of the methodloseEdges, given integersi andj, is to construct a new graph by copying a given graph but omitting the edge from nodei to nodej, if any, and the edge from nodej to nodei, if any:

class Graph {    int edges[][];    public Graph(int[][] edges) { this.edges = edges; }    public Graph loseEdges(int i, int j) {        int n = edges.length;        int[][] newedges = new int[n][];        for (int k = 0; k < n; ++k) {edgelist:{            int z;search:{            if (k == i) {                for (z = 0; z < edges[k].length; ++z) {                    if (edges[k][z] == j) break search;                }            } else if (k == j) {                for (z = 0; z < edges[k].length; ++z) {                    if (edges[k][z] == i) break search;                }            }            // No edge to be deleted; share this list.            newedges[k] = edges[k];            break edgelist;} //search            // Copy the list, omitting the edge at position z.            int m = edges[k].length - 1;            int ne[] = new int[m];            System.arraycopy(edges[k], 0, ne, 0, z);            System.arraycopy(edges[k], z+1, ne, z, m-z);            newedges[k] = ne;} //edgelist        }        return new Graph(newedges);    }}

Note the use of two statement labels,edgelist andsearch, and the use ofbreak 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 nodei to nodej, and the test for an edge from nodej to nodei.


14.16. Thecontinue Statement

Acontinue statement may occur only in awhile,do, orfor statement; statements of these three kinds are callediteration statements. Control passes to the loop-continuation point of an iteration statement.

ContinueStatement:
continue [Identifier];

Acontinue statement with no label attempts to transfer control to the innermost enclosingwhile,do, orfor statement of the immediately enclosing method, constructor, or initializer; this statement, which is called thecontinue target, then immediately ends the current iteration and begins a new one.

To be precise, such acontinue statement always completes abruptly, the reason being acontinue with no label.

If nowhile,do, orfor statement of the immediately enclosing method, constructor, or initializer contains thecontinue statement, a compile-time error occurs.

Acontinue statement with labelIdentifier attempts to transfer control to the enclosing labeled statement (§14.7) that has the sameIdentifier as its label; that statement, which is called thecontinue target, then immediately ends the current iteration and begins a new one.

To be precise, acontinue statement with labelIdentifier always completes abruptly, the reason being acontinue with labelIdentifier.

The continue target must be awhile,do, orfor statement, or a compile-time error occurs.

Acontinue 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 withIdentifier as its label in the immediately enclosing method, constructor, initializer, or lambda body contains thecontinue statement, a compile-time error occurs.

It can be seen, then, that acontinue statement always completes abruptly.

See the descriptions of thewhile statement (§14.12),do statement (§14.13), andfor statement (§14.14) for a discussion of the handling of abrupt termination because ofcontinue.

The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are anytry statements (§14.20) within the continue target whosetry blocks orcatch clauses contain thecontinue statement, then anyfinally clauses of thosetry statements are executed, in order, innermost to outermost, before control is transferred to the continue target. Abrupt completion of afinally clause can disrupt the transfer of control initiated by acontinue statement.

Example 14.16-1. Thecontinue Statement

In theGraph class in§14.15, one of thebreak statements is used to finish execution of the entire body of the outermostfor loop. This break can be replaced by acontinue if thefor loop itself is labeled:

class Graph {    int edges[][];    public Graph(int[][] edges) { this.edges = edges; }    public Graph loseEdges(int i, int j) {        int n = edges.length;        int[][] newedges = new int[n][];edgelists:        for (int k = 0; k < n; ++k) {            int z;search:{            if (k == i) {                for (z = 0; z < edges[k].length; ++z) {                    if (edges[k][z] == j) break search;                }            } else if (k == j) {                for (z = 0; z < edges[k].length; ++z) {                    if (edges[k][z] == i) break search;                }            }            // No edge to be deleted; share this list.            newedges[k] = edges[k];            continue edgelists;} //search            // Copy the list, omitting the edge at position z.            int m = edges[k].length - 1;            int ne[] = new int[m];            System.arraycopy(edges[k], 0, ne, 0, z);            System.arraycopy(edges[k], z+1, ne, z, m-z);            newedges[k] = ne;        } //edgelists        return new Graph(newedges);    }}

Which to use, if either, is largely a matter of programming style.


14.17. Thereturn Statement

Areturn statement returns control to the invoker of a method (§8.4,§15.12) or constructor (§8.8,§15.9).

ReturnStatement:
return [Expression];

Areturn statement iscontained in the innermost constructor, method, initializer, or lambda expression whose body encloses thereturn statement.

It is a compile-time error if areturn statement is contained in an instance initializer or a static initializer (§8.6,§8.7).

Areturn statement with noExpression must be contained in one of the following, or a compile-time error occurs:

  • A method that is declared, using the keywordvoid, not to return a value (§8.4.5)

  • A constructor (§8.8.7)

  • A lambda expression (§15.27)

Areturn statement with noExpression attempts to transfer control to the invoker of the method, constructor, or lambda body that contains it. To be precise, areturn statement with noExpression always completes abruptly, the reason being a return with no value.

Areturn statement with anExpression 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

TheExpression must denote a variable or a value, or a compile-time error occurs.

When areturn statement with anExpression appears in a method declaration, theExpression must be assignable (§5.2) to the declared return type of the method, or a compile-time error occurs.

Areturn statement with anExpression attempts to transfer control to the invoker of the method or lambda body that contains it; the value of theExpression becomes the value of the method invocation. More precisely, execution of such areturn statement first evaluates theExpression. If the evaluation of theExpression completes abruptly for some reason, then thereturn statement completes abruptly for that reason. If evaluation of theExpression completes normally, producing a valueV, then thereturn statement completes abruptly, the reason being a return with valueV.

If the expression is of typefloat 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 typedouble 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 areturn statement always completes abruptly.

The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are anytry statements (§14.20) within the method or constructor whosetry blocks orcatch clauses contain thereturn statement, then anyfinally clauses of thosetry statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of afinally clause can disrupt the transfer of control initiated by areturn statement.

14.18. Thethrow Statement

Athrow 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 atry statement (§14.20) is found that catches the thrown value. If no suchtry statement is found, then execution of the thread (§17 (Threads and Locks)) that executed thethrow is terminated (§11.3) after invocation of theuncaughtException method for the thread group to which the thread belongs.

ThrowStatement:
throwExpression;

TheExpression in athrow statement must either denote a variable or value of a reference type which is assignable (§5.2) to the typeThrowable, or denote the null reference, or a compile-time error occurs.

The reference type of theExpression will always be a class type (since no interface types are assignable toThrowable) which is not parameterized (since a subclass ofThrowable 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 theExpression is an unchecked exception class (§11.1.1) or the null type (§4.1).

  • Thethrow statement is contained in thetry block of atry statement (§14.20) and it is not the case that thetry statement can throw an exception of the type of theExpression. (In this case we say the thrown value iscaught by thetry statement.)

  • Thethrow statement is contained in a method or constructor declaration and the type of theExpression is assignable (§5.2) to at least one type listed in thethrows clause (§8.4.6,§8.8.5) of the declaration.

The exception types that athrow statement can throw are specified in§11.2.2.

Athrow statement first evaluates theExpression. Then:

  • If evaluation of theExpression completes abruptly for some reason, then thethrow completes abruptly for that reason.

  • If evaluation of theExpression completes normally, producing a non-null valueV, then thethrow statement completes abruptly, the reason being athrow with valueV.

  • If evaluation of theExpression completes normally, producing anull value, then an instanceV' of classNullPointerException is created and thrown instead ofnull. Thethrow statement then completes abruptly, the reason being athrow with valueV'.

It can be seen, then, that athrow statement always completes abruptly.

If there are any enclosingtry statements (§14.20) whosetry blocks contain thethrow statement, then anyfinally clauses of thosetry statements are executed as control is transferred outward, until the thrown value is caught. Note that abrupt completion of afinally clause can disrupt the transfer of control initiated by athrow statement.

If athrow statement is contained in a method declaration or a lambda expression, but its value is not caught by sometry statement that contains it, then the invocation of the method completes abruptly because of thethrow.

If athrow statement is contained in a constructor declaration, but its value is not caught by sometry statement that contains it, then the class instance creation expression that invoked the constructor will complete abruptly because of thethrow (§15.9.4).

If athrow 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 sometry statement that contains it. If at run time, despite this check, the value is not caught by sometry statement that contains thethrow statement, then the value is rethrown if it is an instance of classError or one of its subclasses; otherwise, it is wrapped in anExceptionInInitializerError object, which is then thrown (§12.4.2).

If athrow 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 sometry statement that contains it, or the type of the thrown exception (or one of its superclasses) occurs in thethrows clause of every constructor of the class.

By convention, user-declared throwable types should usually be declared to be subclasses of classException, which is a subclass of classThrowable (§11.1.1).

14.19. Thesynchronized Statement

Asynchronized 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.

SynchronizedStatement:
synchronized(Expression)Block

The type ofExpression must be a reference type, or a compile-time error occurs.

Asynchronized statement is executed by first evaluating theExpression. Then:

  • If evaluation of theExpression completes abruptly for some reason, then thesynchronized statement completes abruptly for the same reason.

  • Otherwise, if the value of theExpression isnull, aNullPointerException is thrown.

  • Otherwise, let the non-null value of theExpression beV. The executing thread locks the monitor associated withV. Then theBlock is executed, and then there is a choice:

    • If execution of theBlock completes normally, then the monitor is unlocked and thesynchronized statement completes normally.

    • If execution of theBlock completes abruptly for any reason, then the monitor is unlocked and thesynchronized statement completes abruptly for the same reason.

The locks acquired bysynchronized statements are the same as the locks that are acquired implicitly bysynchronized 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 usesynchronized methods or thesynchronized statement in a conventional manner to achieve mutual exclusion.

Example 14.19-1. Thesynchronized Statement

class Test {    public static void main(String[] args) {        Test t = new Test();        synchronized(t) {            synchronized(t) {                System.out.println("made it!");            }        }    }}

This program produces the output:

made it!

Note that this program would deadlock if a single thread were not permitted to lock a monitor more than once.


14.20. Thetry statement

Atry statement executes a block. If a value is thrown and thetry statement has one or morecatch clauses that can catch it, then control will be transferred to the first suchcatch clause. If thetry statement has afinally clause, then another block of code is executed, no matter whether thetry block completes normally or abruptly, and no matter whether acatch clause is first given control.

TryStatement:
tryBlockCatches
tryBlock [Catches]Finally
TryWithResourcesStatement
Catches:
CatchClause {CatchClause}
CatchClause:
catch(CatchFormalParameter)Block
CatchFormalParameter:
{VariableModifier}CatchTypeVariableDeclaratorId
CatchType:
UnannClassType {|ClassType}
Finally:
finallyBlock

See§8.3 forUnannClassType. The following productions from§4.3,§8.3, and§8.4.1 are shown here for convenience:

VariableModifier:
(one of)
Annotationfinal
VariableDeclaratorId:
Dims:

TheBlock immediately after the keywordtry is called thetry block of thetry statement.

TheBlock immediately after the keywordfinally is called thefinally block of thetry statement.

Atry statement may havecatch clauses, also calledexception handlers.

Acatch clause declares exactly one parameter, which is called anexception parameter.

It is a compile-time error iffinal 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 (calledalternatives). The alternatives of a union are syntactically separated by|.

Acatch clause whose exception parameter is denoted as a single class type is called auni-catch clause.

Acatch clause whose exception parameter is denoted as a union of types is called amulti-catch clause.

Each class type used in the denotation of the type of an exception parameter must be the classThrowable or a subclass ofThrowable, 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 alternativesDi andDj (ij) whereDi is a subtype ofDj (§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 alternativesD1|D2| ...|Dn is lub(D1,D2, ...,Dn).

An exception parameter of a multi-catch clause is implicitly declaredfinal if it is not explicitly declaredfinal.

It is a compile-time error if an exception parameter that is implicitly or explicitly declaredfinal is assigned to within the body of thecatch clause.

An exception parameter of a uni-catch clause is never implicitly declaredfinal, but it may be explicitly declaredfinal or be effectively final (§4.12.4).

An implicitlyfinal 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 declaredfinal, so will never occur as the left-hand operand of an assignment operator, but it isnot 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 explicitfinal 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 declaredfinal, then removing thefinal 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 thecatch 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 thecatch clause and thus will no longer be considered effectively final.

The exception types that atry statement can throw are specified in§11.2.2.

The relationship of the exceptions thrown by thetry block of atry statement and caught by thecatch clauses (if any) of thetry statement is specified in§11.2.3.

Exception handlers are considered in left-to-right order: the earliest possiblecatch 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, acatch clause where the type of the exception parameter is denoted as a unionD1|D2|...|Dn is equivalent to a sequence ofncatch clauses where the types of the exception parameters are class typesD1,D2, ...,Dn respectively. In theBlock of each of thencatch clauses, the declared type of the exception parameter is lub(D1,D2, ...,Dn). For example, the following code:

try {    ... throws ReflectiveOperationException ...}catch (ClassNotFoundException | IllegalAccessException ex) {    ... body ...}

is semantically equivalent to the following code:

try {    ... throws ReflectiveOperationException ...}catch (final ClassNotFoundException ex1) {    final ReflectiveOperationException ex = ex1;    ... body ...}catch (final IllegalAccessException ex2) {    final ReflectiveOperationException ex = ex2;    ... body ...}

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 aclass file without duplication.

Afinally clause ensures that thefinally block is executed after thetry block and anycatch block that might be executed, no matter how control leaves thetry block orcatch block. Handling of thefinally block is rather complex, so the two cases of atry statement with and without afinally block are described separately (§14.20.1,§14.20.2).

Atry statement is permitted to omitcatch clauses and afinally clause if it is atry-with-resources statement (§14.20.3).

14.20.1. Execution oftry-catch

Atry statement without afinally block is executed by first executing thetry block. Then there is a choice:

  • If execution of thetry block completes normally, then no further action is taken and thetry statement completes normally.

  • If execution of thetry block completes abruptly because of athrow of a valueV, then there is a choice:

    • If the run-time type ofV is assignment compatible with (§5.2) a catchable exception class of anycatch clause of thetry statement, then the first (leftmost) suchcatch clause is selected. The valueV is assigned to the parameter of the selectedcatch clause, and theBlock of thatcatch clause is executed, and then there is a choice:

      • If that block completes normally, then thetry statement completes normally.

      • If that block completes abruptly for any reason, then thetry statement completes abruptly for the same reason.

    • If the run-time type ofV is not assignment compatible with a catchable exception class of anycatch clause of thetry statement, then thetry statement completes abruptly because of athrow of the valueV.

  • If execution of thetry block completes abruptly for any other reason, then thetry statement completes abruptly for the same reason.

Example 14.20.1-1. Catching An Exception

class BlewIt extends Exception {    BlewIt() { }    BlewIt(String s) { super(s); }}class Test {    static void blowUp() throws BlewIt { throw new BlewIt(); }    public static void main(String[] args) {        try {            blowUp();        } catch (RuntimeException r) {            System.out.println("Caught RuntimeException");        } catch (BlewIt b) {            System.out.println("Caught BlewIt");        }    }}

Here, the exceptionBlewIt is thrown by the methodblowUp. Thetry-catch statement in the body ofmain has twocatch clauses. The run-time type of the exception isBlewIt which is not assignable to a variable of typeRuntimeException, but is assignable to a variable of typeBlewIt, so the output of the example is:

Caught BlewIt

14.20.2. Execution oftry-finally andtry-catch-finally

Atry statement with afinally block is executed by first executing thetry block. Then there is a choice:

  • If execution of thetry block completes normally, then thefinally block is executed, and then there is a choice:

    • If thefinally block completes normally, then thetry statement completes normally.

    • If thefinally block completes abruptly for reasonS, then thetry statement completes abruptly for reasonS.

  • If execution of thetry block completes abruptly because of athrow of a valueV, then there is a choice:

    • If the run-time type ofV is assignment compatible with a catchable exception class of anycatch clause of thetry statement, then the first (leftmost) suchcatch clause is selected. The valueV is assigned to the parameter of the selectedcatch clause, and theBlock of thatcatch clause is executed. Then there is a choice:

      • If thecatch block completes normally, then thefinally block is executed. Then there is a choice:

        • If thefinally block completes normally, then thetry statement completes normally.

        • If thefinally block completes abruptly for any reason, then thetry statement completes abruptly for the same reason.

      • If thecatch block completes abruptly for reasonR, then thefinally block is executed. Then there is a choice:

        • If thefinally block completes normally, then thetry statement completes abruptly for reasonR.

        • If thefinally block completes abruptly for reasonS, then thetry statement completes abruptly for reasonS (and reasonR is discarded).

    • If the run-time type ofV is not assignment compatible with a catchable exception class of anycatch clause of thetry statement, then thefinally block is executed. Then there is a choice:

      • If thefinally block completes normally, then thetry statement completes abruptly because of athrow of the valueV.

      • If thefinally block completes abruptly for reasonS, then thetry statement completes abruptly for reasonS (and thethrow of valueV is discarded and forgotten).

  • If execution of thetry block completes abruptly for any other reasonR, then thefinally block is executed, and then there is a choice:

    • If thefinally block completes normally, then thetry statement completes abruptly for reasonR.

    • If thefinally block completes abruptly for reasonS, then thetry statement completes abruptly for reasonS (and reasonR is discarded).

Example 14.20.2-1. Handling An Uncaught Exception Withfinally

class BlewIt extends Exception {    BlewIt() { }    BlewIt(String s) { super(s); }}class Test {    static void blowUp() throws BlewIt {        throw new NullPointerException();    }    public static void main(String[] args) {        try {            blowUp();        } catch (BlewIt b) {            System.out.println("Caught BlewIt");        } finally {            System.out.println("Uncaught Exception");        }    }}

This program produces the output:

Uncaught ExceptionException in thread "main" java.lang.NullPointerException        at Test.blowUp(Test.java:7)        at Test.main(Test.java:11)

TheNullPointerException (which is a kind ofRuntimeException) that is thrown by methodblowUp is not caught by thetry statement inmain, because aNullPointerException is not assignable to a variable of typeBlewIt. This causes thefinally clause to execute, after which the thread executingmain, 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

Atry-with-resources statement is parameterized with variables (known asresources) that are initialized before execution of thetry block and closed automatically, in the reverse order from which they were initialized, after execution of thetry block.catch clauses and afinally clause are often unnecessary when resources are closed automatically.

TryWithResourcesStatement:
ResourceSpecification:
ResourceList:
Resource:

See§8.3 forUnannType. The following productions from§4.3,§8.3, and§8.4.1 are shown here for convenience:

VariableModifier:
(one of)
Annotationfinal
VariableDeclaratorId:
Dims:

Aresource specification declares one or more local variables with initializer expressions to act asresources for thetry statement.

It is a compile-time error for a resource specification to declare two variables with the same name.

It is a compile-time error iffinal appears more than once as a modifier for each variable declared in a resource specification.

A variable declared in a resource specification is implicitly declaredfinal (§4.12.4) if it is not explicitly declaredfinal.

The type of a variable declared in a resource specification must be a subtype ofAutoCloseable, or a compile-time error occurs.

The scope and shadowing of a variable declared in a resource specification is specified in§6.3 and§6.4.

Resources are initialized in left-to-right order. If a resource fails to initialize (that is, its initializer expression throws an exception), then all resources initialized so far by thetry-with-resources statement are closed. If all resources initialize successfully, thetry block executes as normal and then all non-null resources of thetry-with-resources statement are closed.

Resources are closed in the reverse order from that in which they were initialized. A resource is closed only if it initialized to a non-null value. An exception from the closing of one resource does not prevent the closing of other resources. Such an exception issuppressed if an exception was thrown previously by an initializer, thetry block, or the closing of a resource.

Atry-with-resources statement whose resource specification declares multiple resources is treated as if it were multipletry-with-resources statements, each of which has a resource specification that declares a single resource. When atry-with-resources statement withn resources (n > 1) is translated, the result is atry-with-resources statement withn-1 resources. Aftern such translations, there aren nestedtry-catch-finally statements, and the overall translation is complete.

14.20.3.1. Basictry-with-resources

Atry-with-resources statement with nocatch clauses orfinally clause is called abasictry-with-resources statement.

The meaning of a basictry-with-resources statement:

try ({VariableModifier} R Identifier =Expression ...)Block

is given by the following translation to a local variable declaration and atry-catch-finally statement:

{    final{VariableModifierNoFinal} R Identifier =Expression;    Throwable #primaryExc = null;    tryResourceSpecification_tailBlock    catch (Throwable #t) {        #primaryExc = #t;        throw #t;    } finally {        if (Identifier != null) {            if (#primaryExc != null) {                try {Identifier.close();                } catch (Throwable #suppressedExc) {                    #primaryExc.addSuppressed(#suppressedExc);                }            } else {Identifier.close();            }        }    }}

{VariableModifierNoFinal} is defined as{VariableModifier} withoutfinal, if present.

#t,#primaryExc, and#suppressedExc are automatically generated identifiers that are distinct from any other identifiers (automatically generated or otherwise) that are in scope at the point where thetry-with-resources statement occurs.

If the resource specification declares one resource, thenResourceSpecification_tail is empty (and thetry-catch-finally statement is not itself atry-with-resources statement).

If the resource specification declaresn > 1 resources, thenResourceSpecification_tail consists of the 2nd, 3rd, ...,n'th resources declared in resource specification, in the same order (and thetry-catch-finally statement is itself atry-with-resources statement).

Reachability and definite assignment rules for the basictry-with-resources statement are implicitly specified by the translation above.

In a basictry-with-resources statement that manages a single resource:

  • If the initialization of the resource completes abruptly because of athrow of a valueV, then thetry-with-resources statement completes abruptly because of athrow of the valueV.

  • If the initialization of the resource completes normally, and thetry block completes abruptly because of athrow of a valueV, then:

    • If the automatic closing of the resource completes normally, then thetry-with-resources statement completes abruptly because of athrow of the valueV.

    • If the automatic closing of the resource completes abruptly because of athrow of a valueV2, then thetry-with-resources statement completes abruptly because of athrow of valueV withV2 added to the suppressed exception list ofV.

  • If the initialization of the resource completes normally, and thetry block completes normally, and the automatic closing of the resource completes abruptly because of athrow of a valueV, then thetry-with-resources statement completes abruptly because of athrow of the valueV.

In a basictry-with-resources statement that manages multiple resources:

  • If the initialization of a resource completes abruptly because of athrow of a valueV, then:

    • If the automatic closings of all successfully initialized resources (possibly zero) complete normally, then thetry-with-resources statement completes abruptly because of athrow of the valueV.

    • If the automatic closings of all successfully initialized resources (possibly zero) complete abruptly because ofthrows of valuesV1...Vn, then thetry-with-resources statement completes abruptly because of athrow of the valueV with any remaining valuesV1...Vn added to the suppressed exception list ofV.

  • If the initialization of all resources completes normally, and thetry block completes abruptly because of athrow of a valueV, then:

    • If the automatic closings of all initialized resources complete normally, then thetry-with-resources statement completes abruptly because of athrow of the valueV.

    • If the automatic closings of one or more initialized resources complete abruptly because ofthrows of valuesV1...Vn, then thetry-with-resources statement completes abruptly because of athrow of the valueV with any remaining valuesV1...Vn added to the suppressed exception list ofV.

  • If the initialization of every resource completes normally, and thetry block completes normally, then:

    • If one automatic closing of an initialized resource completes abruptly because of athrow of valueV, and all other automatic closings of initialized resources complete normally, then thetry-with-resources statement completes abruptly because of athrow of the valueV.

    • If more than one automatic closing of an initialized resource completes abruptly because ofthrows of valuesV1...Vn, then thetry-with-resources statement completes abruptly because of athrow of the valueV1 with any remaining valuesV2...Vn added to the suppressed exception list ofV1 (whereV1 is the exception from the rightmost resource failing to close andVn is the exception from the leftmost resource failing to close).

14.20.3.2. Extendedtry-with-resources

Atry-with-resources statement with at least onecatch clause and/or afinally clause is called anextendedtry-with-resources statement.

The meaning of an extendedtry-with-resources statement:

tryResourceSpecificationBlock[Catches][Finally]

is given by the following translation to a basictry-with-resources statement nested inside atry-catch ortry-finally ortry-catch-finally statement:

try {    tryResourceSpecification        Block}[Catches][Finally]

The effect of the translation is to put the resource specification "inside" thetry statement. This allows acatch clause of an extendedtry-with-resources statement to catch an exception due to the automatic initialization or closing of any resource.

Furthermore, all resources will have been closed (or attempted to be closed) by the time thefinally block is executed, in keeping with the intent of thefinally keyword.

14.21. Unreachable Statements

It is a compile-time error if a statement cannot be executed because it isunreachable.

This section is devoted to a precise explanation of the word "reachable." The idea is that there must be some possible execution path from the beginning of the constructor, method, instance initializer, or static initializer that contains the statement to the statement itself. The analysis takes into account the structure of statements. Except for the special treatment ofwhile,do, andfor statements whose condition expression has the constant valuetrue, the values of expressions are not taken into account in the flow analysis.

For example, a Java compiler will accept the code:

{    int n = 5;    while (n > 7) k = 2;}

even though the value ofn is known at compile time and in principle it can be known at compile time that the assignment tok can never be executed.

The rules in this section define two technical terms:

  • whether a statement isreachable

  • whether a statementcan complete normally

The definitions here allow a statement to complete normally only if it is reachable.

To shorten the description of the rules, the customary abbreviation "iff" is used to mean "if and only if."

A reachablebreak statementexits a statement if, within the break target, either there are notry statements whosetry blocks contain thebreak statement, or there aretry statements whosetry blocks contain thebreak statement and allfinally clauses of thosetry statements can complete normally.

This definition is based on the logic around "attempts to transfer control" in§14.15.

Acontinue statementcontinues ado statement if, within thedo statement, either there are notry statements whosetry blocks contain thecontinue statement, or there aretry statements whosetry blocks contain thecontinue statement and allfinally clauses of thosetry statements can complete normally.

The rules are as follows:

  • The block that is the body of a constructor, method, instance initializer, or static initializer is reachable.

  • An empty block that is not a switch block can complete normally iff it is reachable.

    A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally.

    The first statement in a non-empty block that is not a switch block is reachable iff the block is reachable.

    Every other statementS in a non-empty block that is not a switch block is reachable iff the statement precedingS can complete normally.

  • A local class declaration statement can complete normally iff it is reachable.

  • A local variable declaration statement can complete normally iff it is reachable.

  • An empty statement can complete normally iff it is reachable.

  • A labeled statement can complete normally if at least one of the following is true:

    • The contained statement can complete normally.

    • There is a reachablebreak statement that exits the labeled statement.

    The contained statement is reachable iff the labeled statement is reachable.

  • An expression statement can complete normally iff it is reachable.

  • Anif-then statement can complete normally iff it is reachable.

    Thethen-statement is reachable iff theif-then statement is reachable.

    Anif-then-else statement can complete normally iff thethen-statement can complete normally or theelse-statement can complete normally.

    Thethen-statement is reachable iff theif-then-else statement is reachable.

    Theelse-statement is reachable iff theif-then-else statement is reachable.

    This handling of anif statement, whether or not it has anelse part, is rather unusual. The rationale is given at the end of this section.

  • Anassert statement can complete normally iff it is reachable.

  • Aswitch statement can complete normally iff at least one of the following is true:

    • The switch block is empty or contains only switch labels.

    • The last statement in the switch block can complete normally.

    • There is at least one switch label after the last switch block statement group.

    • The switch block does not contain adefault label.

    • There is a reachablebreak statement that exits theswitch statement.

  • A switch block is reachable iff itsswitch statement is reachable.

  • A statement in a switch block is reachable iff itsswitch statement is reachable and at least one of the following is true:

    • It bears acase ordefault label.

    • There is a statement preceding it in the switch block and that preceding statement can complete normally.

  • Awhile statement can complete normally iff at least one of the following is true:

    • Thewhile statement is reachable and the condition expression is not a constant expression (§15.28) with valuetrue.

    • There is a reachablebreak statement that exits thewhile statement.

    The contained statement is reachable iff thewhile statement is reachable and the condition expression is not a constant expression whose value isfalse.

  • Ado statement can complete normally iff at least one of the following is true:

    • The contained statement can complete normally and the condition expression is not a constant expression (§15.28) with valuetrue.

    • Thedo statement contains a reachablecontinue statement with no label, and thedo statement is the innermostwhile,do, orfor statement that contains thatcontinue statement, and thecontinue statement continues thatdo statement, and the condition expression is not a constant expression with valuetrue.

    • Thedo statement contains a reachablecontinue statement with a labelL, and thedo statement has labelL, and thecontinue statement continues thatdo statement, and the condition expression is not a constant expression with valuetrue.

    • There is a reachablebreak statement that exits thedo statement.

    The contained statement is reachable iff thedo statement is reachable.

  • A basicfor statement can complete normally iff at least one of the following is true:

    • Thefor statement is reachable, there is a condition expression, and the condition expression is not a constant expression (§15.28) with valuetrue.

    • There is a reachablebreak statement that exits thefor statement.

    The contained statement is reachable iff thefor statement is reachable and the condition expression is not a constant expression whose value isfalse.

  • An enhancedfor statement can complete normally iff it is reachable.

  • Abreak,continue,return, orthrow statement cannot complete normally.

  • Asynchronized statement can complete normally iff the contained statement can complete normally.

    The contained statement is reachable iff thesynchronized statement is reachable.

  • Atry statement can complete normally iff both of the following are true:

    • Thetry block can complete normally or anycatch block can complete normally.

    • If thetry statement has afinally block, then thefinally block can complete normally.

  • Thetry block is reachable iff thetry statement is reachable.

  • Acatch blockC is reachable iff both of the following are true:

    • Either the type ofC's parameter is an unchecked exception type orException or a superclass ofException, or some expression orthrow statement in thetry block is reachable and can throw a checked exception whose type is assignable to the type ofC's parameter. (An expression is reachable iff the innermost statement containing it is reachable.)

      See§15.6 for normal and abrupt completion of expressions.

    • There is no earliercatch blockA in thetry statement such that the type ofC's parameter is the same as or a subclass of the type ofA's parameter.

  • TheBlock of acatch block is reachable iff thecatch block is reachable.

  • If afinally block is present, it is reachable iff thetry statement is reachable.

Onemight expect theif statement to be handled in the following manner:

  • Anif-then statement can complete normally iff at least one of the following is true:

    • Theif-then statement is reachable and the condition expression is not a constant expression whose value istrue.

    • Thethen-statement can complete normally.

    Thethen-statement is reachable iff theif-then statement is reachable and the condition expression is not a constant expression whose value isfalse.

  • Anif-then-else statement can complete normally iff thethen-statement can complete normally or theelse-statement can complete normally.

    Thethen-statement is reachable iff theif-then-else statement is reachable and the condition expression is not a constant expression whose value isfalse.

    Theelse-statement is reachable iff theif-then-else statement is reachable and the condition expression is not a constant expression whose value istrue.

This approach would be consistent with the treatment of other control structures. However, in order to allow the if statement to be used conveniently for "conditional compilation" purposes, the actual rules differ.

As an example, the following statement results in a compile-time error:

while (false) { x=3; }

because the statementx=3; is not reachable; but the superficially similar case:

if (false) { x=3; }

does not result in a compile-time error. An optimizing compiler may realize that the statementx=3; will never be executed and may choose to omit the code for that statement from the generatedclass file, but the statementx=3; is not regarded as "unreachable" in the technical sense specified here.

The rationale for this differing treatment is to allow programmers to define "flag variables" such as:

static final boolean DEBUG = false;

and then write code such as:

if (DEBUG) { x=3; }

The idea is that it should be possible to change the value ofDEBUG fromfalse totrue or fromtrue tofalse and then compile the code correctly with no other changes to the program text.

This ability to "conditionally compile" has no relationship to binary compatibility (§13 (Binary Compatibility)). If a set of classes that use such a "flag" variable are compiled and conditional code is omitted, it does not suffice later to distribute just a new version of the class or interface that contains the definition of the flag. The classes that use the flag will not see its new value, so their behavior may be surprising, but noLinkageError will occur. A change to the value of a flag is, therefore, binary compatible with pre-existing binaries, but not behaviorally compatible.


Prev   Next
Chapter 13. Binary Compatibility Home Chapter 15. Expressions

Legal Notice

[8]ページ先頭

©2009-2025 Movatter.jp