Chapter 16. Definite Assignment
Table of Contents
- 16.1. Definite Assignment and Expressions
-
- 16.1.1. Boolean Constant Expressions
- 16.1.2. Conditional-And Operator
&& - 16.1.3. Conditional-Or Operator
|| - 16.1.4. Logical Complement Operator
! - 16.1.5. Conditional Operator
? : - 16.1.6. Conditional Operator
? : - 16.1.7. Other Expressions of Type
boolean - 16.1.8. Assignment Expressions
- 16.1.9. Operators
++and-- - 16.1.10. Other Expressions
- 16.2. Definite Assignment and Statements
-
- 16.2.1. Empty Statements
- 16.2.2. Blocks
- 16.2.3. Local Class Declaration Statements
- 16.2.4. Local Variable Declaration Statements
- 16.2.5. Labeled Statements
- 16.2.6. Expression Statements
- 16.2.7.
ifStatements - 16.2.8.
assertStatements - 16.2.9.
switchStatements - 16.2.10.
whileStatements - 16.2.11.
doStatements - 16.2.12.
forStatements - 16.2.13.
break,continue,return, andthrowStatements - 16.2.14.
synchronizedStatements - 16.2.15.
tryStatements
- 16.3. Definite Assignment and Parameters
- 16.4. Definite Assignment and Array Initializers
- 16.5. Definite Assignment and Enum Constants
- 16.6. Definite Assignment and Anonymous Classes
- 16.7. Definite Assignment and Member Types
- 16.8. Definite Assignment and Static Initializers
- 16.9. Definite Assignment, Constructors, and Instance Initializers
Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) 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 (or, for a field, the simple name of the field qualified by this) occurring anywhere in an expression except as the left-hand operand of the simple assignment operator = (§15.26.1).
For every access of a local variable or blank final field x, x must be definitely assigned before the access, or a compile-time error occurs.
Similarly, every blank final variable must be assigned at most once; it must be definitely unassigned when an assignment to it occurs.
Such an assignment is defined to occur if and only if either the simple name of the variable (or, for a field, its simple name qualified by this) occurs on the left hand side of an assignment operator.
For every assignment to a blank final variable, the variable must be definitely unassigned before the assignment, or a compile-time error occurs.
The remainder of this chapter is devoted to a precise explanation of the words "definitely assigned before" and "definitely unassigned before".
The idea behind definite assignment is that an assignment to the local variable or blank final field must occur on every possible execution path to the access. Similarly, the idea behind definite unassignment is that no other assignment to the blank final variable is permitted to occur on any possible execution path to an assignment.
The analysis takes into account the structure of statements and expressions; it also provides a special treatment of the expression operators !, &&, ||, and ? :, and of boolean-valued constant expressions.
Except for the special treatment of the conditional boolean operators &&, ||, and ? : and of boolean-valued constant expressions, the values of expressions are not taken into account in the flow analysis.
Example 16-1. Definite Assignment Considers Structure of Statements and Expressions
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.
On the other hand, the code:
{
int k;
while (n < 4) {
k = n;
if (k >= 5) break;
n = 6;
}
System.out.println(k); /* k is not "definitely assigned"
before this statement */
}
must be rejected by a Java compiler, because in this case the while statement is not guaranteed to execute its body as far as the rules of definite assignment are concerned.
Example 16-2. Definite Assignment Does Not Consider Values of Expressions
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 statement */
}
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.28.
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 this statement */
}
and so compiling this program must cause a compile-time error to occur.
Example 16-3. Definite Unassignment
A Java compiler will accept the code:
void unflow(boolean flag) {
final int k;
if (flag) {
k = 3;
System.out.println(k);
}
else {
k = 4;
System.out.println(k);
}
}
as far as definite unassignment of k is concerned, because the rules outlined in this section allow it to tell that k is assigned at most once (indeed, exactly once) no matter whether the flag is true or false. But the rules do not accept the variation:
void unflow(boolean flag) {
final int k;
if (flag) {
k = 3;
System.out.println(k);
}
if (!flag) {
k = 4;
System.out.println(k); /* k is not "definitely unassigned"
before this statement */
}
}
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 several technical terms:
-
whether a variable is definitely assigned before a statement or expression;
-
whether a variable is definitely unassigned before a statement or expression;
-
whether a variable is definitely assigned after a statement or expression; and
-
whether a variable is definitely unassigned after a statement or expression.
For boolean-valued expressions, the last two are refined into four cases:
-
whether a variable is definitely assigned after the expression when true;
-
whether a variable is definitely unassigned after the expression when true;
-
whether a variable is definitely assigned after the expression when false; and
-
whether a variable is definitely unassigned 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 necessarily executed (more properly, evaluated)).
The phrase "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 need 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.
The statement "V is definitely unassigned after X" (where V is a variable and X is a statement or expression) means "V is definitely unassigned after X if X completes normally".
An even more peculiar consequence of this definition is that "V is definitely unassigned after break;" is always true! Because a break statement never completes normally, it is vacuously true that V has not been assigned a value if the break statement completes normally. (For that matter, it is also vacuously true that the moon is made of green cheese if the break statement completes normally.)
In all, there are four possibilities for a variable V after a statement or expression has been executed:
-
V is definitely assigned and is not definitely unassigned.
(The flow analysis rules prove that an assignment to V has occurred.)
-
V is definitely unassigned and is not definitely assigned.
(The flow analysis rules prove that an assignment to V has not occurred.)
-
V is not definitely assigned and is not definitely unassigned.
(The rules cannot prove whether or not an assignment to V has occurred.)
-
V is definitely assigned and is definitely unassigned.
(It is impossible for the statement or expression to complete normally.)
To shorten the rules, the customary abbreviation "iff" is used to mean "if and only if". We also use an abbreviation convention: if a rule contains one or more occurrences of "[un]assigned" then it stands for two rules, one with every occurrence of "[un]assigned" replaced by "definitely assigned" and one with every occurrence of "[un]assigned" replaced by "definitely unassigned".
For example:
-
V is [un]assigned after an empty statement iff it is [un]assigned before the empty statement.
should be understood to stand for two rules:
-
V is definitely assigned after an empty statement iff it is definitely assigned before the empty statement.
-
V is definitely unassigned after an empty statement iff it is definitely unassigned before the empty statement.
Throughout the rest of this chapter, we will, unless explicitly stated otherwise, write V to represent a local variable or blank final field which is in scope (§6.3). Likewise, we will use a, b, c, and e to represent expressions, and S and T to represent statements. We will use the phrase "a is V" to mean that a is either the simple name of the variable V, or V's simple name qualified by this (ignoring parentheses). We will use the phrase "a is not V" to mean the negation of "a is V".
The definite unassignment analysis of loop statements raises a special problem. Consider the statement while (. In order to determine whether V is definitely unassigned within some subexpression of e) Se, we need to determine whether V is definitely unassigned before e. One might argue, by analogy with the rule for definite assignment (§16.2.10), that V is definitely unassigned before e iff it is definitely unassigned before the while statement. However, such a rule is inadequate for our purposes. If e evaluates to true, the statement S will be executed. Later, if V is assigned by S, then in the following iteration(s) V will have already been assigned when e is evaluated. Under the rule suggested above, it would be possible to assign V multiple times, which is exactly what we have sought to avoid by introducing these rules.
A revised rule would be: "V is definitely unassigned before e iff it is definitely unassigned before the while statement and definitely unassigned after S". However, when we formulate the rule for S, we find: "V is definitely unassigned before S iff it is definitely unassigned after e when true". This leads to a circularity. In effect, V is definitely unassigned before the loop condition e only if it is unassigned after the loop as a whole!
We break this vicious circle using a hypothetical analysis of the loop condition and body. For example, if we assume that V is definitely unassigned before e (regardless of whether V really is definitely unassigned before e), and can then prove that V was definitely unassigned after e then we know that e does not assign V. This is stated more formally as:
Assuming V is definitely unassigned before e, V is definitely unassigned after e.
Variations on the above analysis are used to define well founded definite unassignment rules for all loop statements in the Java programming language.
-
V is [un]assigned after any constant expression (§15.28) whose value is
truewhen false. -
V is [un]assigned after any constant expression whose value is
falsewhen true. -
V is [un]assigned after any constant expression whose value is
truewhen true iff V is [un]assigned before the constant expression. -
V is [un]assigned after any constant expression whose value is
falsewhen false iff V is [un]assigned before the constant expression. -
V is [un]assigned after a boolean-valued constant expression
eiff V is [un]assigned afterewhen true and V is [un]assigned afterewhen false.This is equivalent to saying that V is [un]assigned after
eiff V is [un]assigned beforee.
Because 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, the first two rules are vacuously satisfied. They are helpful in analyzing expressions involving the operators && (§16.1.2), || (§16.1.3), ! (§16.1.4), and ? : (§16.1.5).
-
V is [un]assigned after
a&&b(§15.23) when true iff V is [un]assigned afterbwhen true. -
V is [un]assigned after
a&&bwhen false iff V is [un]assigned afterawhen false and V is [un]assigned afterbwhen false. -
V is [un]assigned before
aiff V is [un]assigned beforea&&b. -
V is [un]assigned before
biff V is [un]assigned afterawhen true. -
V is [un]assigned after
a&&biff V is [un]assigned aftera&&bwhen true and V is [un]assigned aftera&&bwhen false.
-
V is [un]assigned after
a||b(§15.24) when true iff V is [un]assigned afterawhen true and V is [un]assigned afterbwhen true. -
V is [un]assigned after
a||bwhen false iff V is [un]assigned afterbwhen false. -
V is [un]assigned before
aiff V is [un]assigned beforea||b. -
V is [un]assigned before
biff V is [un]assigned afterawhen false. -
V is [un]assigned after
a||biff V is [un]assigned aftera||bwhen true and V is [un]assigned aftera||bwhen false.
-
V is [un]assigned after
!a(§15.15.6) when true iff V is [un]assigned afterawhen false. -
V is [un]assigned after
!awhen false iff V is [un]assigned afterawhen true. -
V is [un]assigned before
aiff V is [un]assigned before!a. -
V is [un]assigned after
!aiff V is [un]assigned after!awhen true and V is [un]assigned after!awhen false.This is equivalent to saying that V is [un]assigned after
!aiff V is [un]assigned aftera.
Suppose that b and c are boolean-valued expressions.
-
V is [un]assigned after
a?b:c(§15.25) when true iff V is [un]assigned afterbwhen true and V is [un]assigned aftercwhen true. -
V is [un]assigned after
a?b:cwhen false iff V is [un]assigned afterbwhen false and V is [un]assigned aftercwhen false. -
V is [un]assigned before
aiff V is [un]assigned beforea?b:c. -
V is [un]assigned before
biff V is [un]assigned afterawhen true. -
V is [un]assigned before
ciff V is [un]assigned afterawhen false. -
V is [un]assigned after
a?b:ciff V is [un]assigned aftera?b:cwhen true and V is [un]assigned aftera?b:cwhen false.
Suppose that b and c are expressions that are not boolean-valued.
-
V is [un]assigned after
a?b:c(§15.25) iff V is [un]assigned afterband V is [un]assigned afterc. -
V is [un]assigned before
aiff V is [un]assigned beforea?b:c. -
V is [un]assigned before
biff V is [un]assigned afterawhen true. -
V is [un]assigned before
ciff V is [un]assigned afterawhen false.
Suppose that e is an expression of type boolean and is not a boolean constant expression, logical complement expression !a, conditional-and expression a && b, conditional-or expression a || b, or conditional expression a ? b : c.
-
V is [un]assigned after
ewhen true iff V is [un]assigned aftere. -
V is [un]assigned after
ewhen false iff V is [un]assigned aftere.
Consider 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 (§15.26).
-
V is definitely assigned after the assignment expression iff either:
-
ais V, or -
V is definitely assigned after
b.
-
-
V is definitely unassigned after the assignment expression iff
ais not V and V is definitely unassigned afterb. -
V is [un]assigned before
aiff V is [un]assigned before the assignment expression. -
V is [un]assigned before
biff V is [un]assigned aftera.
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 first rule for definite assignment stated above includes the disjunct "a is V" even for compound assignment expressions, not just simple assignments, 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. A similar remark applies to the inclusion of the conjunct "a is not V" in the first rule for definite unassignment stated above.
-
V is definitely assigned after
++a(§15.15.1),--a(§15.15.2),a++(§15.14.2), ora--(§15.14.3) iff eitherais V or V is definitely assigned after the operand expression. -
V is definitely unassigned after
++a,--a,a++, ora--iffais not V and V is definitely unassigned after the operand expression. -
V is [un]assigned before
aiff V is [un]assigned before++a,--a,a++, ora--.
If an expression is not a boolean constant expression, and is not a preincrement expression ++a, predecrement expression --a, postincrement expression a++, postdecrement expression a--, logical complement expression !a, conditional-and expression a && b, conditional-or expression a || b, conditional expression a ? b : c, or assignment expression, then the following rules apply:
-
If the expression has no subexpressions, V is [un]assigned after the expression iff V is [un]assigned before the expression.
This case applies to literals, names,
this(both qualified and unqualified), unqualified class instance creation expressions with no arguments, initialized array creation expressions whose initializers contain no expressions, unqualified superclass field access expressions, named method invocations with no arguments, and unqualified superclass method invocations with no arguments. -
If the expression has subexpressions, V is [un]assigned after the expression iff V is [un]assigned after its rightmost immediate subexpression.
There is a piece of subtle reasoning behind the assertion that a variable V can be known to be definitely unassigned after a method invocation. Taken by itself, at face value and without qualification, such an assertion is not always true, because an invoked method can perform assignments. But it must be remembered that, for the purposes of the Java programming language, the concept of definite unassignment is applied only to blank final variables. If V is a blank final local variable, then only the method to which its declaration belongs can perform assignments to V. If V is a blank final field, then only a constructor or an initializer for the class containing the declaration for V can perform assignments to V; no method can perform assignments to V. Finally, explicit constructor invocations (§8.8.7.1) are handled specially (§16.9); although they are syntactically similar to expression statements containing method invocations, they are not expression statements and therefore the rules of this section do not apply to explicit constructor invocations.
For any immediate subexpression y of an expression x, V is [un]assigned before y iff one of the following is true:
-
yis the leftmost immediate subexpression ofxand V is [un]assigned beforex. -
yis the right-hand operand of a binary operator and V is [un]assigned after the left-hand operand. -
xis an array access,yis the subexpression within the brackets, and V is [un]assigned after the subexpression before the brackets. -
xis a primary method invocation expression,yis the first argument expression in the method invocation expression, and V is [un]assigned after the primary expression that computes the target object. -
xis a method invocation expression or a class instance creation expression;yis an argument expression, but not the first; and V is [un]assigned after the argument expression to the left ofy. -
xis a qualified class instance creation expression,yis the first argument expression in the class instance creation expression, and V is [un]assigned after the primary expression that computes the qualifying object. -
xis an array instance creation expression;yis a dimension expression, but not the first; and V is [un]assigned after the dimension expression to the left ofy. -
xis an array instance creation expression initialized via an array initializer;yis the array initializer inx; and V is [un]assigned after the dimension expression to the left ofy.
-
V is [un]assigned after an empty statement (§14.6) iff it is [un]assigned before the empty statement.
-
A blank
finalmember field V is definitely assigned (and moreover is not definitely unassigned) before the block (§14.2) that is the body of any method in the scope of V and before the declaration of any class declared within the scope of V. -
A local variable V is definitely unassigned (and moreover is not definitely assigned) before the block that is the body of the constructor, method, instance initializer or static initializer that declares V.
-
Let C be a class declared within the scope of V. Then V is definitely assigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C iff V is definitely assigned before the declaration of C.
Note that there are no rules that would allow us to conclude that V is definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C. We can informally conclude that V is not definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C, but there is no need for such a rule to be stated explicitly.
-
V is [un]assigned after an empty block iff V is [un]assigned before the empty block.
-
V is [un]assigned after a non-empty block iff V is [un]assigned after the last statement in the block.
-
V is [un]assigned before the first statement of the block iff V is [un]assigned before the block.
-
V is [un]assigned before any other statement S of the block iff V is [un]assigned after the statement immediately preceding S in the block.
We say that V is definitely unassigned everywhere in a block B iff:
-
V is definitely unassigned before B.
-
V is definitely assigned after
ein every assignment expression V=e, V+=e, V-=e, V*=e, V/=e, V%=e, V<<=e, V>>=e, V>>>=e, V&=e, V|=e, or V^=ethat occurs in B. -
V is definitely assigned before every expression
++V,--V, V++, or V--that occurs in B.
These conditions are counterintuitive and require some explanation. Consider a simple assignment V = e. If V is definitely assigned after e, then either:
-
The assignment occurs in dead code, and V is vacuously definitely assigned. In this case, the assignment will not actually take place, and we can assume that V is not being assigned by the assignment expression. Or:
-
V was already assigned by an earlier expression prior to
e. In this case the current assignment will cause a compile-time error.
So, we can conclude that if the conditions are met by a program that causes no compile time error, then any assignments to V in B will not actually take place at run time.
-
V is [un]assigned after a local class declaration statement (§14.3) iff V is [un]assigned before the local class declaration statement.
-
V is [un]assigned after a local variable declaration statement (§14.4) that contains no variable initializers iff V is [un]assigned before the local variable declaration statement.
-
V is definitely assigned after a local variable declaration statement that contains at least one variable initializer iff either V is definitely assigned after the last variable initializer in the local variable declaration statement or the last variable initializer in the declaration is in the declarator that declares V.
-
V is definitely unassigned after a local variable declaration statement that contains at least one variable initializer iff V is definitely unassigned after the last variable initializer in the local variable declaration statement and the last variable initializer in the declaration is not in the declarator that declares V.
-
V is [un]assigned before the first variable initializer in a local variable declaration statement iff V is [un]assigned before the local variable declaration statement.
-
V is definitely assigned before any variable initializer
eother than the first one in the local variable declaration statement iff either V is definitely assigned after the variable initializer to the left ofeor the initializer expression to the left ofeis in the declarator that declares V. -
V is definitely unassigned before any variable initializer
eother than the first one in the local variable declaration statement iff V is definitely unassigned after the variable initializer to the left ofeand the initializer expression to the left ofeis not in the declarator that declares V.
-
V is [un]assigned after a labeled statement
L:S (whereLis a label) (§14.7) iff V is [un]assigned after S and V is [un]assigned before everybreakstatement that may exit the labeled statementL:S. -
V is [un]assigned before S iff V is [un]assigned before
L:S.
-
V is [un]assigned after an expression statement
e;(§14.8) iff it is [un]assigned aftere. -
V is [un]assigned before
eiff it is [un]assigned beforee;.
The following rules apply to a statement if ( (§14.9.1): e) S
-
V is [un]assigned after
if (iff V is [un]assigned after S and V is [un]assigned aftere) Sewhen false. -
V is [un]assigned before
eiff V is [un]assigned beforeif (.e) S -
V is [un]assigned before S iff V is [un]assigned after
ewhen true.
The following rules apply to a statement if (e) S else
T (§14.9.2):
-
V is [un]assigned after
if (iff V is [un]assigned after S and V is [un]assigned after T.e) S else T -
V is [un]assigned before
eiff V is [un]assigned beforeif (.e) S else T -
V is [un]assigned before S iff V is [un]assigned after
ewhen true. -
V is [un]assigned before T iff V is [un]assigned after
ewhen false.
The following rules apply both to a statement assert
and to a statement e1assert (§14.10): e1 :
e2
-
V is [un]assigned before
e1iff V is [un]assigned before theassertstatement. -
V is definitely assigned after the
assertstatement iff V is definitely assigned before theassertstatement. -
V is definitely unassigned after the
assertstatement iff V is definitely unassigned before theassertstatement and V is definitely unassigned aftere1when true.
The following rule applies to a statement assert : e1 : e2
-
V is [un]assigned before
e2iff V is [un]assigned aftere1when false.
-
V is [un]assigned after a
switchstatement (§14.11) iff all of the following are true:-
Either there is a
defaultlabel in the switch block or V is [un]assigned after the switch expression. -
Either there are no switch labels in the switch block that do not begin a block-statement-group (that is, there are no switch labels immediately before the "
}" that ends the switch block) or V is [un]assigned after the switch expression. -
Either the switch block contains no block-statement-groups or V is [un]assigned after the last block-statement of the last block-statement-group.
-
V is [un]assigned before every
breakstatement that may exit theswitchstatement.
-
-
V is [un]assigned before the switch expression iff V is [un]assigned before the
switchstatement.
If a switch block contains at least one block-statement-group, then the following rules also apply:
-
V is [un]assigned before the first block-statement of the first block-statement-group in the switch block iff V is [un]assigned after the switch expression.
-
V is [un]assigned before the first block-statement of any block-statement-group other than the first iff V is [un]assigned after the switch expression and V is [un]assigned after the preceding block-statement.
-
V is [un]assigned after
while ((§14.12) iff V is [un]assigned aftere) Sewhen false and V is [un]assigned before everybreakstatement for which thewhilestatement is the break target. -
V is definitely assigned before
eiff V is definitely assigned before thewhilestatement. -
V is definitely unassigned before
eiff all of the following are true:-
V is definitely unassigned before the
whilestatement. -
Assuming V is definitely unassigned before
e, V is definitely unassigned after S. -
Assuming V is definitely unassigned before
e, V is definitely unassigned before everycontinuestatement for which thewhilestatement is the continue target.
-
-
V is [un]assigned before S iff V is [un]assigned after
ewhen true.
-
V is [un]assigned after
do S while ((§14.13) iff V is [un]assigned aftere);ewhen false and V is [un]assigned before everybreakstatement for which thedostatement is the break target. -
V is definitely assigned before S iff V is definitely assigned before the
dostatement. -
V is definitely unassigned before S iff all of the following are true:
-
V is definitely unassigned before the
dostatement. -
Assuming V is definitely unassigned before S, V is definitely unassigned after
ewhen true.
-
-
V is [un]assigned before
eiff V is [un]assigned after S and V is [un]assigned before everycontinuestatement for which thedostatement is the continue target.
The rules herein cover the basic for statement (§14.14.1). Since the enhanced for statement (§14.14.2) is defined by translation to a basic for statement, no special rules need to be provided for it.
-
V is [un]assigned after a
forstatement iff both of the following are true:-
Either a condition expression is not present or V is [un]assigned after the condition expression when false.
-
V is [un]assigned before every
breakstatement for which theforstatement is the break target.
-
-
V is [un]assigned before the initialization part of the
forstatement iff V is [un]assigned before theforstatement. -
V is definitely assigned before the condition part of the
forstatement iff V is definitely assigned after the initialization part of theforstatement. -
V is definitely unassigned before the condition part of the
forstatement iff all of the following are true:-
V is definitely unassigned after the initialization part of the
forstatement. -
Assuming V is definitely unassigned before the condition part of the
forstatement, V is definitely unassigned after the contained statement. -
Assuming V is definitely unassigned before the contained statement, V is definitely unassigned before every
continuestatement for which theforstatement is the continue target.
-
-
V is [un]assigned before the contained statement iff either of the following is true:
-
A condition expression is present and V is [un]assigned after the condition expression when true.
-
No condition expression is present and V is [un]assigned after the initialization part of the
forstatement.
-
-
V is [un]assigned before the incrementation part of the
forstatement iff V is [un]assigned after the contained statement and V is [un]assigned before everycontinuestatement for which theforstatement is the continue target.
-
If the initialization part of the
forstatement is a local variable declaration statement, the rules of §16.2.4 apply. -
Otherwise, if the initialization part is empty, then V is [un]assigned after the initialization part iff V is [un]assigned before the initialization part.
-
Otherwise, three rules apply:
-
V is [un]assigned after the initialization part iff V is [un]assigned after the last expression statement in the initialization part.
-
V is [un]assigned before the first expression statement in the initialization part iff V is [un]assigned before the initialization part.
-
V is [un]assigned before an expression statement S other than the first in the initialization part iff V is [un]assigned after the expression statement immediately preceding S.
-
-
If the incrementation part of the
forstatement is empty, then V is [un]assigned after the incrementation part iff V is [un]assigned before the incrementation part. -
Otherwise, three rules apply:
-
V is [un]assigned after the incrementation part iff V is [un]assigned after the last expression statement in the incrementation part.
-
V is [un]assigned before the first expression statement in the incrementation part iff V is [un]assigned before the incrementation part.
-
V is [un]assigned before an expression statement S other than the first in the incrementation part iff V is [un]assigned after the expression statement immediately preceding S.
-
-
By convention, we say that V is [un]assigned after any
break,continue,return, orthrowstatement (§14.15, §14.16, §14.17, §14.18).The notion that a variable is "[un]assigned after" a statement or expression really means "is [un]assigned after the statement or expression completes normally". Because a
break,continue,return, orthrowstatement never completes normally, it vacuously satisfies this notion. -
In a
returnstatement with an expressioneor athrowstatement with an expressione, V is [un]assigned beforeeiff V is [un]assigned before thereturnorthrowstatement.
-
V is [un]assigned after
synchronized ((§14.19) iff V is [un]assigned after S.e) S -
V is [un]assigned before
eiff V is [un]assigned before the statementsynchronized (.e) S -
V is [un]assigned before S iff V is [un]assigned after
e.
These rules apply to every try statement (§14.20), whether or not it has a finally block:
-
V is [un]assigned before the
tryblock iff V is [un]assigned before thetrystatement. -
V is definitely assigned before a
catchblock iff V is definitely assigned before thetryblock. -
V is definitely unassigned before a
catchblock iff all of the following are true:-
V is definitely unassigned after the
tryblock. -
V is definitely unassigned before every
returnstatement that belongs to thetryblock. -
V is definitely unassigned after
ein every statement of the formthrowethat belongs to thetryblock. -
V is definitely unassigned after every
assertstatement that occurs in thetryblock. -
V is definitely unassigned before every
breakstatement that belongs to thetryblock and whose break target contains (or is) thetrystatement. -
V is definitely unassigned before every
continuestatement that belongs to thetryblock and whose continue target contains thetrystatement.
-
If a try statement does not have a finally block, then this rule also applies:
-
V is [un]assigned after the
trystatement iff V is [un]assigned after thetryblock and V is [un]assigned after everycatchblock in thetrystatement.
If a try statement does have a finally block, then these rules also apply:
-
V is definitely assigned after the
trystatement iff at least one of the following is true:-
V is definitely assigned after the
tryblock and V is definitely assigned after everycatchblock in thetrystatement. -
V is definitely assigned after the
finallyblock. -
V is definitely unassigned after a
trystatement iff V is definitely unassigned after thefinallyblock.
-
-
V is definitely assigned before the
finallyblock iff V is definitely assigned before thetrystatement. -
V is definitely unassigned before the
finallyblock iff all of the following are true:-
V is definitely unassigned after the
tryblock. -
V is definitely unassigned before every
returnstatement that belongs to thetryblock. -
V is definitely unassigned after
ein every statement of the formthrowethat belongs to thetryblock. -
V is definitely unassigned after every
assertstatement that occurs in thetryblock. -
V is definitely unassigned before every
breakstatement that belongs to thetryblock and whose break target contains (or is) thetrystatement. -
V is definitely unassigned before every
continuestatement that belongs to thetryblock and whose continue target contains thetrystatement. -
V is definitely unassigned after every
catchblock of thetrystatement.
-
-
A formal parameter V of a method or constructor (§8.4.1, §8.8.1) is definitely assigned (and moreover is not definitely unassigned) before the body of the method or constructor.
-
An exception parameter V of a
catchclause (§14.20) is definitely assigned (and moreover is not definitely unassigned) before the body of thecatchclause.
-
V is [un]assigned after an empty array initializer (§10.6) iff V is [un]assigned before the empty array initializer.
-
V is [un]assigned after a non-empty array initializer iff V is [un]assigned after the last variable initializer in the array initializer.
-
V is [un]assigned before the first variable initializer of the array initializer iff V is [un]assigned before the array initializer.
-
V is [un]assigned before any other variable initializer
eof the array initializer iff V is [un]assigned after the variable initializer to the left ofein the array initializer.
The rules determining when a variable is definitely assigned or definitely unassigned before an enum constant (§8.9.1) are given in §16.8.
This is because an enum constant is essentially a static final field (§8.3.1.1, §8.3.1.2) that is initialized with a class instance creation expression (§15.9).
-
V is definitely assigned before the declaration of a class body of an enum constant with no arguments that is declared within the scope of V iff V is definitely assigned before the enum constant.
-
V is definitely assigned before the declaration of a class body of an enum constant with arguments that is declared within the scope of V iff V is definitely assigned after the last argument expression of the enum constant
The definite assignment/unassignment status of any construct within the class body of an enum constant is governed by the usual rules for classes.
-
V is [un]assigned before the first argument to an enum constant iff it is [un]assigned before the enum constant.
-
V is [un]assigned before
y(an argument of an enum constant, but not the first) iff V is [un]assigned after the argument to the left ofy.
-
V is definitely assigned before an anonymous class declaration (§15.9.5) that is declared within the scope of V iff V is definitely assigned after the class instance creation expression that declares the anonymous class.
It should be clear that if an anonymous class is implicitly defined by an enum constant, the rules of §16.5 apply.
Let C be a class, and let V be a blank final member field of C. Then:
Let C be a class declared within the scope of V. Then:
-
V is definitely assigned before a member type declaration of C iff V is definitely assigned before the declaration of C.
Let C be a class declared within the scope of V. Then:
-
V is definitely assigned before an enum constant (§8.9.1) or static variable initializer (§8.3.2) of C iff V is definitely assigned before the declaration of C.
Note that there are no rules that would allow us to conclude that V is definitely unassigned before a static variable initializer or enum constant. We can informally conclude that V is not definitely unassigned before any static variable initializer of C, but there is no need for such a rule to be stated explicitly.
Let C be a class, and let V be a blank static final member field of C, declared in C. Then:
-
V is definitely unassigned (and moreover is not definitely assigned) before the leftmost enum constant, static initializer (§8.7), or static variable initializer of C.
-
V is [un]assigned before an enum constant, static initializer, or static variable initializer of C other than the leftmost iff V is [un]assigned after the preceding enum constant, static initializer, or static variable initializer of C.
Let C be a class, and let V be a blank static final member field of C, declared in a superclass of C. Then:
-
V is definitely assigned (and moreover is not definitely unassigned) before every enum constant of C.
-
V is definitely assigned (and moreover is not definitely unassigned) before the block that is the body of a static initializer of C.
-
V is definitely assigned (and moreover is not definitely unassigned) before every static variable initializer of C.
Let C be a class declared within the scope of V. Then:
-
V is definitely assigned before an instance variable initializer (§8.3.2) of C iff V is definitely assigned before the declaration of C.
Note that there are no rules that would allow us to conclude that V is definitely unassigned before an instance variable initializer. We can informally conclude that V is not definitely unassigned before any instance variable initializer of C, but there is no need for such a rule to be stated explicitly.
Let C be a class, and let V be a blank final non-static member field of C, declared in C. Then:
-
V is definitely unassigned (and moreover is not definitely assigned) before the leftmost instance initializer (§8.6) or instance variable initializer of C.
-
V is [un]assigned before an instance initializer or instance variable initializer of C other than the leftmost iff V is [un]assigned after the preceding instance initializer or instance variable initializer of C.
The following rules hold within the constructors (§8.8.7) of class C:
-
V is definitely assigned (and moreover is not definitely unassigned) after an alternate constructor invocation (§8.8.7.1).
-
V is definitely unassigned (and moreover is not definitely assigned) before an explicit or implicit superclass constructor invocation (§8.8.7.1).
-
If C has no instance initializers or instance variable initializers, then V is not definitely assigned (and moreover is definitely unassigned) after an explicit or implicit superclass constructor invocation.
-
If C has at least one instance initializer or instance variable initializer then V is [un]assigned after an explicit or implicit superclass constructor invocation iff V is [un]assigned after the rightmost instance initializer or instance variable initializer of C.
Let C be a class, and let V be a blank final member field of C, declared in a superclass of C. Then:
-
V is definitely assigned (and moreover is not definitely unassigned) before the block that is the body of a constructor or instance initializer of C.
-
V is definitely assigned (and moreover is not definitely unassigned) before every instance variable initializer of C.
© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.