Contents | Prev | Next | Index

**
CHAPTER
16 **

Each local variable must have a *definitely assigned* value when any access of
its value occurs. An access to its value consists of the simple name of the variable
occurring anywhere in an expression except as the left-hand operand of the simple
assignment operator `=`

.

A Java compiler must carry out a specific conservative flow analysis to make sure that, for every access of a local variable, the local variable is definitely assigned before the access; otherwise a compile-time error must occur.

The remainder of this chapter is devoted to a precise explanation of the words "definitely assigned before". The idea is that an assignment to the local variable must occur on every possible execution path to the access from the beginning of the constructor, method, or static initializer that contains the access. The analysis takes into account the structure of statements and expressions; it also provides a special treatment of the expression operators `!`

, `&&`

, `||`

, and `? :`

, the operators `&`

, `|`

, `^`

, `==`

, and `!=`

with `boolean`

operands, and boolean-valued constant expressions. For example, a Java compiler recognizes that `k`

is definitely assigned before its access (as an argument of a method invocation) in the code:

{ int k; if (v > 0 && (k = System.in.read()) >= 0) System.out.println(k); }because the access occurs only if the value of the expression:

v > 0 && (k = System.in.read()) >= 0is true, and the value can be

`true`

only if the assignment to `k`

is executed (more
properly, evaluated). Similarly, a Java compiler will recognize that in the code:
{ int k; while (true) { k = n; if (k >= 5) break; n = 6; } System.out.println(k); }the variable

`k`

is definitely assigned by the `while`

statement because the condition
expression `true`

never has the value `false`

, so only the `break`

statement can
cause the `while`

statement to complete normally, and `k`

is definitely assigned
before the `break`

statement.
Except for the special treatment of certain boolean operators and of boolean-valued constant expressions, the values of expressions are not taken into account in the flow analysis. For example, a Java compiler must produce a compile-time error for the code:

{ int k; int n = 5; if (n > 2) k = 3; System.out.println(k); // k is not "definitely assigned" before this }even though the value of

`n`

is known at compile time, and in principle it can be
known at compile time that the assignment to `k`

will always be executed (more
properly, evaluated). A Java compiler must operate according to the rules laid out
in this section. The rules recognize only constant expressions; in this example, the
expression `n`

`>`

`2`

is not a constant expression as defined in §15.27.
As another example, a Java compiler will accept the code:

void flow(boolean flag) { int k; if (flag) k = 3; else k = 4; System.out.println(k); }as far as definite assignment of

`k`

is concerned, because the rules outlined in this
section allow it to tell that `k`

is assigned no matter whether the flag is `true`

or
`false`

. But the rules do not accept the variation:
void flow(boolean flag) { int k; if (flag) k = 3; if (!flag) k = 4; System.out.println(k); // k is not "definitely assigned" before here }and so compiling this program must cause a compile-time error to occur.

In order to precisely specify all the cases of definite assignment, the rules in this section define two technical terms:

- whether a local variable is
*definitely assigned before*a statement or expression, and - whether a local variable is
*definitely assigned after*a statement or expression.

- whether a local variable is
*definitely assigned after*the expression*when true*, and - whether a local variable is
*definitely assigned after*the expression*when false*.

```
a && ((k=m) > 5)
```

when the expression is `true`

but not when the expression is `false`

(because if `a`

is
`false`

, then the assignment to `k`

is not executed (more properly, evaluated)).
The statement "*V* is definitely assigned after *X*" (where *V* is a local variable and *X* is a statement or expression) means "*V* is definitely assigned after *X* if *X* completes normally". If *X* completes abruptly, the assignment may not have occurred, and the rules stated here take this into account. A peculiar consequence of this definition is that "*V* is definitely assigned after `break;`

" is always true! Because a `break`

statement never completes normally, it is vacuously true that *V* has been assigned a value if the `break`

statement completes normally.

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

Let *V* be a local variable. Let *a*, *b*, *c*, and *e *be expressions. Let *S* and *T* be statements.

`true`

when
false. `false`

when true.
A constant expression whose value is `true`

never has the value `false`

, and a constant expression whose value is `false`

never has the value `true`

, these definitions are vacuously satisfied. They are helpful in analyzing expressions involving the boolean operators `&&`

, `||`

, and `!`

`(`

§16.1.3, §16.1.4, §16.1.5).

- If the expression has no subexpressions,
*V*is definitely assigned after the expression iff*V*is definitely assigned before the expression. This case applies to literals and simple names. - Otherwise,
*V*is definitely assigned after the expression iff*V*is definitely assigned after the expression when true and*V*is definitely assigned after the expression when false.

`&&`

*V*is definitely assigned after*a*`&&`

*b*when true iff*V*is definitely assigned after*a*when true or*V*is definitely assigned after*b*when true.*V*is definitely assigned after*a*`&&`

*b*when false iff*V*is definitely assigned after*a*when false and*V*is definitely assigned after*b*when false.*V*is definitely assigned before*a*iff*V*is definitely assigned before*a*`&&`

*b*.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*when true.

`||`

*V*is definitely assigned after*a*`||`

*b*when true iff*V*is definitely assigned after*a*when true and*V*is definitely assigned after*b*when true.*V*is definitely assigned after*a*`||`

*b*when false iff*V*is definitely assigned after*a*when false or*V*is definitely assigned after*b*when false.*V*is definitely assigned before*a*iff*V*is definitely assigned before*a*`||`

*b*.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*when false.

`!`

*V*is definitely assigned after`!`

*a*when true iff*V*is definitely assigned after*a*when false.*V*is definitely assigned after`!`

*a*when false iff*V*is definitely assigned after*a*when true.*V*is definitely assigned before*a*iff*V*is definitely assigned before`!`

*a*.

`&`

*V*is definitely assigned after*a*`&`

*b*when true iff*V*is definitely assigned after*a*when true or*V*is definitely assigned after*b*when true.*V*is definitely assigned after*a*`&`

*b*when false iff at least one of the following is true:*V*is definitely assigned after*b*. (Note that if*V*is definitely assigned after*a*, it follows that*V*is definitely assigned after*b*.)*V*is definitely assigned after*a*when false and*V*is definitely assigned after*b*when false.

*V*is definitely assigned before*a*iff*V*is definitely assigned before*a*`&`

*b*.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*.

`|`

*V*is definitely assigned after*a*`|`

*b*when true iff at least one of the following is true:*V*is definitely assigned after*b*. (Note that if*V*is definitely assigned after*a*, it follows that*V*is definitely assigned after*b*.)*V*is definitely assigned after*a*when true and*V*is definitely assigned after*b*when true.

*V*is definitely assigned after*a*`|`

*b*when false iff*V*is definitely assigned after*a*when false or*V*is definitely assigned after*b*when false.*V*is definitely assigned before*a*iff*V*is definitely assigned before*a*`|`

*b*.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*.

`^`

*V*is definitely assigned after*a*`^`

*b*when true iff at least one of the following is true:*V*is definitely assigned after*b*.*V*is definitely assigned after*a*when true and*V*is definitely assigned after*b*when true.*V*is definitely assigned after*a*when false and*V*is definitely assigned after*b*when false.

*V*is definitely assigned after*a*`^`

*b*when false iff at least one of the following is true:*V*is definitely assigned after*b*.*V*is definitely assigned after*a*when true and*V*is definitely assigned after*b*when false.*V*is definitely assigned after*a*when false and*V*is definitely assigned after*b*when true.

*V*is definitely assigned before*a*iff*V*is definitely assigned before*a*`^`

*b*.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*.

`==`

*V*is definitely assigned after*a*`==`

*b*when true iff at least one of the following is true:*V*is definitely assigned after*b*.*V*is definitely assigned after*a*when true and*V*is definitely assigned after*b*when false.*V*is definitely assigned after*a*when false and*V*is definitely assigned after*b*when true.

*V*is definitely assigned after*a*`==`

*b*when false iff at least one of the following is true:*V*is definitely assigned after*b*.*V*is definitely assigned after*a*when true and*V*is definitely assigned after*b*when true.*V*is definitely assigned after*a*when false and*V*is definitely assigned after*b*when false.

*V*is definitely assigned before*a*iff*V*is definitely assigned before*a*`==`

*b*.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*.

`!=`

`!=`

`^`

`? :`

*V*is definitely assigned after*a*`?`

*b*`:`

*c*when true iff both of the following are true:*V*is definitely assigned before*b*or*V*is definitely assigned after*b*when true.*V*is definitely assigned before*c*or*V*is definitely assigned after*c*when true.

*V*is definitely assigned after*a*`?`

*b*`:`

*c*when false iff both of the following are true:*V*is definitely assigned before*b*or*V*is definitely assigned after*b*when false.*V*is definitely assigned before*c*or*V*is definitely assigned after*c*when false.

*V*is definitely assigned before*a*iff*V*is definitely assigned before*a*`?`

*b*`:`

*c*.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*when true.*V*is definitely assigned before*c*iff*V*is definitely assigned after*a*when false.

`? :`

*V*is definitely assigned after*a*`?`

*b*`:`

*c*iff both of the following are true:*V*is definitely assigned before*a*iff*V*is definitely assigned before*a*`?`

*b*`:`

*c*.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*when true.*V*is definitely assigned before*c*iff*V*is definitely assigned after*a*when false.

`=`

`&=`

`|=`

`^=`

*V*is definitely assigned before*a*iff*V*is definitely assigned before the assignment expression.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*.*V*is definitely assigned after*a*`=`

*b*when true iff either*a*is*V*or*V*is definitely assigned after the right-hand operand expression when true.*V*is definitely assigned after*a*`=`

*b*when false iff either*a*is*V*or*V*is definitely assigned after the right-hand operand expression when false.*V*is definitely assigned after*a*`&=`

*b*when true iff either*a*is*V*or*V*would be definitely assigned after*a*`&`

*b*(in the same context) when true.*V*is definitely assigned after*a*`&=`

*b*when false iff either*a*is*V*or*V*would be definitely assigned after*a*`&`

*b*(in the same context) when false.*V*is definitely assigned after*a*`|=`

*b*when true iff either*a*is*V*or*V*would be definitely assigned after*a*`|`

*b*(in the same context) when true.*V*is definitely assigned after*a*`|=`

*b*when false iff either*a*is*V*or*V*would be definitely assigned after*a*`|`

*b*(in the same context) when false.*V*is definitely assigned after*a*`^=`

*b*when true iff either*a*is*V*or*V*would be definitely assigned after*a*`^`

*b*(in the same context) when true.*V*is definitely assigned after*a*`^=`

*b*when false iff either*a*is*V*or*V*would be definitely assigned after*a*`^`

*b*(in the same context) when false.

`&=`

`=`

`+=`

`-=`

`*=`

`/=`

`%=`

`<<=`

`>>=`

`>>>=`

`&=`

`|=`

`^=`

*V*is definitely assigned after the assignment expression iff either*a*is*V*or*V*is definitely assigned after*b*.*V*is definitely assigned before*a*iff*V*is definitely assigned before the assignment expression.*V*is definitely assigned before*b*iff*V*is definitely assigned after*a*.

`++`

and `--`

*V*is definitely assigned after a preincrement, predecrement, postincrement, or postdecrement expression iff either the operand expression is*V*or*V*is definitely assigned after the operand expression.*V*is definitely assigned before the operand expression iff*V*is definitely assigned before the preincrement, predecrement, postincrement, or postdecrement expression.

- If the expression has no subexpressions,
*V*is definitely assigned after the expression iff*V*is definitely assigned before the expression. This case applies to literals, simple names,`this`

,`super`

, and`null`

. - If the expression has subexpressions,
*V*is definitely assigned after the expression iff*V*is definitely assigned after its rightmost immediate subexpression.

*y*is the right-hand operand of a binary operator and*V*is definitely assigned after the left-hand operand.*x*is an array reference,*y*is the subexpression within the brackets, and*V*is definitely assigned after the subexpression before the brackets.*x*is a method invocation expression for an object;*y*is the first argument expression in the method invocation expression; there is a subexpression whose value is an object to the left of the dot, method name, and left parenthesis of the method invocation expression; and*V*is definitely assigned after this subexpression.*x*is a method invocation expression or class instance creation expression;*y*is an argument expression, but not the first; and*V*is definitely assigned after the argument expression to the left of*y*.*x*is an class instance creation expression;*y*is a dimension expression, but not the first; and*V*is definitely assigned after the dimension expression to the left of*y*.

*V*is definitely assigned after an empty statement iff it is definitely assigned before the empty statement.

*V*is definitely assigned after an empty block iff it is definitely assigned before the empty block.*V*is definitely assigned after a nonempty block iff it is definitely assigned after the last statement in the block.*V*is definitely assigned before the first statement of the block iff it is definitely assigned before the block.*V*is definitely assigned before any other statement*S*of the block iff it is definitely assigned after the statement immediately preceding*S*in the block.

*V*is definitely assigned after a local variable declaration statement that contains no initializers iff it is definitely assigned before the local variable declaration statement.*V*is definitely assigned after a local variable declaration statement that contains initializers iff either it is definitely assigned after the last initializer expression in the local variable declaration statement or the last initializer expression in the declaration is in the declarator that declares*V*.*V*is definitely assigned before the first initializer expression iff it is definitely assigned before the local variable declaration statement.*V*is definitely assigned before any other initializer expression*e*iff either it is definitely assigned after the initializer expression immediately preceding*e*in the local variable declaration statement or the initializer expression immediately preceding*e*in the local variable declaration statement is in the declarator that declares*V*.

*V*is definitely assigned after a labeled statement*L*`:`

*S*(where*L*is a label) iff*V*is definitely assigned after*S*and*V*is definitely assigned before every`break`

statement that may exit the labeled statement*L*`:`

*S*.*V*is definitely assigned before*S*iff*V*is definitely assigned before*L*`:`

*S*.

*V*is definitely assigned after an expression statement*e*`;`

iff it is definitely assigned after*e*.*V*is definitely assigned before*e*iff it is definitely assigned before*e*`;`

.

`if`

Statements*V*is definitely assigned after`if`

`(`

*e*`)`

*S*iff*V*is definitely assigned after*S*and*V*is definitely assigned after*e*when false.*V*is definitely assigned before*e*iff*V*is definitely assigned before`if`

`(`

*e*`)`

*S*.*V*is definitely assigned before*S*iff*V*is definitely assigned after*e*when true.*V*is definitely assigned after`if`

`(`

*e*`)`

*S*`else`

*T*iff*V*is definitely assigned after*S*and*V*is definitely assigned after*T*.*V*is definitely assigned before*e*iff*V*is definitely assigned before`if`

`(`

*e*`)`

*S*`else`

*T*.*V*is definitely assigned before*S*iff*V*is definitely assigned after*e*when true.*V*is definitely assigned before*T*iff*V*is definitely assigned after*e*when false.

`switch`

Statements*V*is definitely assigned after a`switch`

statement iff both of the following are true:- Either the
`switch`

block is empty or*V*is definitely assigned after the last statement of the`switch`

block. *V*is definitely assigned before every`break`

statement that may exit the`switch`

statement.

- Either the
*V*is definitely assigned before the switch expression iff*V*is definitely assigned before the`switch`

statement.*V*is definitely assigned before a statement or local variable declaration statement*S*in the switch block iff at least one of the following is true:

`while`

Statements*V*is definitely assigned after`while`

`(`

*e*`)`

*S*iff*V*is definitely assigned after*e*when false and*V*is definitely assigned before every`break`

statement that may exit the`while`

statement.*V*is definitely assigned before*e*iff*V*is definitely assigned before the`while`

statement.*V*is definitely assigned before*S*iff*V*is definitely assigned after*e*when true.

`do`

Statements*V*is definitely assigned after`do`

*S*`while`

`(`

*e*`);`

iff*V*is definitely assigned after*e*when false and*V*is definitely assigned before every`break`

statement that may exit the`do`

statement.*V*is definitely assigned before*S*iff*V*is definitely assigned before the`do`

statement.*V*is definitely assigned before*e*iff*V*is definitely assigned after*S*and*V*is definitely assigned before every`continue`

statement that may exit the body of the`do`

statement.

`for`

Statements*V*is definitely assigned after a`for`

statement iff both of the following are true:- Either a condition expression is not present or
*V*is definitely assigned after the condition expression when false. *V*is definitely assigned before every`break`

statement that may exit the`for`

statement.

- Either a condition expression is not present or
*V*is definitely assigned before the initialization part of the`for`

statement iff*V*is definitely assigned before the`for`

statement.*V*is definitely assigned before the condition part of the`for`

statement iff*V*is definitely assigned after the initialization part of the`for`

statement.*V*is definitely assigned before the contained statement iff either of the following is true:- A condition expression is present and
*V*is definitely assigned after the condition expression when true. - No condition expression is present and
*V*is definitely assigned after the initialization part of the`for`

statement.

- A condition expression is present and
*V*is definitely assigned before the incrementation part of the`for`

statement iff*V*is definitely assigned after the contained statement and*V*is definitely assigned before every`continue`

statement that may exit the body of the`for`

statement.

- If the initialization part of the
`for`

statement is a local variable declaration statement, the rules of §16.2.3 apply. - Otherwise, if the initialization part is empty, then
*V*is definitely assigned after the initialization part iff*V*is definitely assigned before the initialization part. - Otherwise, three rules apply:
*V*is definitely assigned after the initialization part iff*V*is definitely assigned after the last expression statement in the initialization part.*V*is definitely assigned before the first expression statement in the initialization part iff*V*is definitely assigned before the initialization part.*V*is definitely assigned before an expression statement*E*other than the first in the initialization part iff*V*is definitely assigned after the expression statement immediately preceding*E*.

- If the incrementation part of the
`for`

statement is empty, then*V*is definitely assigned after the incrementation part iff*V*is definitely assigned before the incrementation part. - Otherwise, three rules apply:
*V*is definitely assigned after the incrementation part iff*V*is definitely assigned after the last expression statement in the incrementation part.*V*is definitely assigned before the first expression statement in the incrementation part iff*V*is definitely assigned before the incrementation part.*V*is definitely assigned before an expression statement*E*other than the first in the incrementation part iff*V*is definitely assigned after the expression statement immediately preceding*E*.

`break`

, `continue`

, `return`

, and `throw`

Statements- By convention, we say that
*V*is definitely assigned after any`break`

,`continue`

,`return`

, or`throw`

statement. The notion that a variable is "definitely assigned after" a statement or expression really means "is definitely assigned after the statement or expression completes normally". Because a`break`

,`continue`

,`return`

, or`throw`

statement never completes normally, it vacuously satisfies this notion. - In a
`return`

statement with an expression or a`throw`

statement,*V*is definitely assigned before the expression iff*V*is definitely assigned before the`return`

or`throw`

statement.

`synchronized`

Statements*V*is definitely assigned after`synchronized`

`(`

*e*`)`

*S*iff*V*is definitely assigned after*S*.*V*is definitely assigned before*e*iff*V*is definitely assigned before the statement`synchronized`

`(`

*e*`)`

*S*.*V*is definitely assigned before*S*iff*V*is definitely assigned after*e*.

`try`

Statements*V*is definitely assigned after a`try`

statement iff one of the following is true:*V*is definitely assigned after the try block and*V*is definitely assigned after every catch block in the try statement.- The
`try`

statement has a`finally`

block and*V*is definitely assigned after the`finally`

block.

*V*is definitely assigned before the`try`

block iff*V*is definitely assigned before the`try`

statement.*V*is definitely assigned before a`catch`

block iff*V*is definitely assigned before the`try`

statement.

`finally`

block iff `try`

statement.

Contents | Prev | Next | Index

Java Language Specification (HTML generated by Suzette Pelouch on February 24, 1998)

*Copyright © 1996 Sun Microsystems, Inc.
All rights reserved*

Please send any comments or corrections to doug.kramer@sun.com

Spec-Zone.ru - all specs in one place