Contents | Prev | Next | Index
CHAPTER
16
Definite Assignment
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()) >= 0
is 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.
In order to specify boolean-valued expressions, the latter notion is refined into two cases:
- 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.
Here when true and when false refer to the value of the expression. For example,
the local variable k is definitely assigned a value after evaluation of the expression
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.
16.1 Definite Assignment and Expressions
16.1.1 Boolean Constant Expressions
V is definitely assigned after any constant expression whose value is true
when
false. V is definitely assigned after any constant expression whose value is 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).
16.1.2 Boolean-valued Expressions
For every boolean-valued 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 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.
16.1.3 The Boolean Operator &&
- 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.
16.1.4 The Boolean Operator ||
- 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.
16.1.5 The Boolean Operator !
- 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.
16.1.6 The Boolean Operator &
- 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.
16.1.7 The Boolean Operator |
- 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.
16.1.8 The Boolean Operator ^
- 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.
16.1.9 The Boolean Operator ==
- 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.
16.1.10 The Boolean Operator !=
The rules for a !=
b are identical to the rules for a ^
b (§16.1.8).
16.1.11 The Boolean Operator ? :
Suppose that b and c are boolean-valued expressions.
- 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.
16.1.12 The Conditional Operator ? :
Suppose that b and c are expressions that are not boolean-valued.
- V is definitely assigned after a
?
b :
c iff both of the following are true:
- V is definitely assigned after b.
- V is definitely assigned after c.
- 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.
16.1.13 Boolean Assignment Expressions
Suppose that an assignment expression a =
b, a &=
b, a |=
b, or a ^=
b is boolean-
valued.
- 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.
Note that if a is V and V is not definitely assigned before a compound assignment such as a &=
b, then a compile-time error will necessarily occur. The rules stated above include the disjunct "a is V" so that V will be considered to have been definitely assigned at later points in the code. Including the disjunct "a is V" does not affect the binary decision as to whether a program is acceptable or will result in a compile-time error, but it affects how many different points in the code may be regarded as erroneous, and so in practice it can improve the quality of error reporting.
16.1.14 Other Assignment Expressions
Suppose that an assignment expression a =
b, a +=
b, a -=
b, a *=
b, a /=
b, a %=
b,
a <<=
b, a >>=
b, a >>>=
b, a &=
b, a |=
b, or a ^=
b is not boolean-valued.
- 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.
16.1.15 Operators ++
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.
16.1.16 Other Expressions
If an expression is not boolean-valued and is not a conditional-operator expression
or assignment expression, the following rules apply:
- 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.
For any immediate subexpression y of an expression x, V is definitely assigned
before y iff V is definitely assigned before x or one of the following situations is
true:
- 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.
16.2 Definite Assignment and Statements
16.2.1 Empty Statements
- V is definitely assigned after an empty statement iff it is definitely assigned before the empty statement.
16.2.2 Blocks
- 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.
16.2.3 Local Variable Declaration Statements
- 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.
16.2.4 Labeled Statements
- 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.
16.2.5 Expression Statements
- 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
;
.
16.2.6 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.
16.2.7 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.
- 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:
- V is definitely assigned after the switch expression.
- S is not labeled by a
case
or default
label and V is definitely assigned after the preceding statement.
16.2.8 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.
16.2.9 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.
16.2.10 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.
- 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.
- 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.
16.2.10.1 Initialization Part
- 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.
16.2.10.2 Incrementation Part
- 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.
16.2.11 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.
16.2.12 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.
16.2.13 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.
V is definitely assigned before a finally
block iff V is definitely assigned before
the 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 [email protected]