Source: http://4e00.com/java/java-language-specification-v2/defAssign.doc.html
Timestamp: 2019-04-19 12:14:47+00:00

Document:
Each local variable (§14.4) and every blank final (§4.5.4) field (§8.3.1.2) must have a definitely assigned value when any access of its value occurs. A Java compiler must carry out a specific conservative flow analysis to make sure that, for every access of a local variable or blank final field f, f is definitely assigned before the access; otherwise a compile-time error must occur.
Similarly, every blank final variable must be assigned at most once; it must be definitely unassigned when an assignment to it occurs. A Java compiler must carry out a specific conservative flow analysis to make sure that, for every assignment to a blank final variable, the variable is definitely unassigned before the assignment; otherwise a compile-time error must occur.
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.
is true, and the value can be true only if the assignment to k is executed (more properly, evaluated).
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.
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.
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.
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.
and so compiling this program must cause a compile-time error to occur.
whether a variable is definitely unassigned after a statement or expression.
whether a variable is definitely unassigned after the expression when false.
Here when true and when false refer to the value of the expression.
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.
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".
V is [un]assigned after an empty statement iff it is [un]assigned before the empty statement.
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.
The definite unassignment analysis of loop statements raises a special problem. Consider the statement while (e) S. In order to determine whether V is definitely unassigned within some subexpression of e, we need to determine whether V is definitely unassigned before e. One might argue, by analogy with the rule for definite assignment (§16.2.9), 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!
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 language.
Throughout the rest of this chapter, we will, unless explicitly stated otherwise, write V to represent a local variable or a blank final field (for rules of definite assignment) or a blank final variable (for rules of definite unassignment). Likewise, we will use a, b, c, and e to represent expressions, and S and T to represent statements.
V is [un]assigned after any constant expression whose value is true when false.
V is [un]assigned after any constant expression whose value is false when true.
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 two preceding 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 any constant expression whose value is true when true iff V is [un]assigned before the constant expression.
V is [un]assigned after any constant expression whose value is false when false iff V is [un]assigned before the constant expression.
V is [un]assigned after a && b when true iff V is [un]assigned after b when true.
V is [un]assigned after a && b when false iff V is [un]assigned after a when false and V is [un]assigned after b when false.
V is [un]assigned before a iff V is [un]assigned before a && b.
V is [un]assigned before b iff V is [un]assigned after a when true.
V is [un]assigned after a && b iff V is [un]assigned after a && b when true and V is [un]assigned after a && b when false.
V is [un]assigned after a || b when true iff V is [un]assigned after a when true and V is [un]assigned after b when true.
V is [un]assigned after a || b when false iff V is [un]assigned after b when false.
V is [un]assigned before a iff V is [un]assigned before a || b.
V is [un]assigned before b iff V is [un]assigned after a when false.
V is [un]assigned after a || b iff V is [un]assigned after a || b when true and V is [un]assigned after a || b when false.
V is [un]assigned after !a when true iff V is [un]assigned after a when false.
V is [un]assigned after !a when false iff V is [un]assigned after a when true.
V is [un]assigned before a iff V is [un]assigned before !a.
Suppose that b and c are boolean-valued expressions.
V is [un]assigned after a ? b : c when true iff V is [un]assigned after b when true and V is [un]assigned after c when true.
V is [un]assigned after a ? b : c when false iff V is [un]assigned after b when false and V is [un]assigned after c when false.
V is [un]assigned before a iff V is [un]assigned before a ? b : c.
V is [un]assigned before c iff V is [un]assigned after a when false.
V is [un]assigned after a ? b : c iff V is [un]assigned after a ? b : c when true and V is [un]assigned after a ? b : c when false.
Suppose that b and c are expressions that are not boolean-valued.
V is [un]assigned after a ? b : c iff V is [un]assigned after b and V is [un]assigned after c.
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.
V is definitely assigned after the assignment expression iff either a is V or V is definitely assigned after b.
V is definitely unassigned after the assignment expression iff a is not V and V is definitely unassigned after b.
V is [un]assigned before a iff V is [un]assigned before the assignment expression.
V is [un]assigned before b iff V is [un]assigned after a. 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 [un]assigned after the assignment expression when true iff V is [un]assigned after the assignment expression.
V is [un]assigned after the assignment expression when false iff V is [un]assigned after the assignment expression.
V is definitely assigned after ++a, --a, a++, or a-- iff either a is V or V is definitely assigned after the operand expression.
V is definitely unassigned after ++a, --a, a++, or a-- iff a is not V and V is definitely unassigned after the operand expression.
V is [un]assigned before a iff V is [un]assigned before ++a, --a, a++, or a--.
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.5) are handled specially (§16.8); 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.
y is the leftmost immediate subexpression of x and V is [un]assigned before x.
y is the right-hand operand of a binary operator and V is [un]assigned after the left-hand operand.
x is an array access, y is the subexpression within the brackets, and V is [un]assigned after the subexpression before the brackets.
x is a primary method invocation expression, y is the first argument expression in the method invocation expression, and V is [un]assigned after the primary expression that computes the target object.
x is a method invocation expression or a class instance creation expression; y is an argument expression, but not the first; and V is [un]assigned after the argument expression to the left of y.
x is a qualified class instance creation expression, y is the first argument expression in the class instance creation expression, and V is [un]assigned after the primary expression that computes the qualifying object.
x is an array instance creation expression; y is a dimension expression, but not the first; and V is [un]assigned after the dimension expression to the left of y.
x is an array instance creation expression initialized via an array initializer; y is the array initializer in x; and V is [un]assigned after the dimension expression to the left of y.
A blank final member field V is definitely assigned (and moreover is not definitely unassigned) before the block that is the body of any method in 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.
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 it is [un]assigned before the empty block.
V is [un]assigned after a nonempty block iff it is [un]assigned after the last statement in the block.
V is [un]assigned before the first statement of the block iff it is [un]assigned before the block.
V is [un]assigned before any other statement S of the block iff it is [un]assigned after the statement immediately preceding S in the block.
V is [un]assigned after a local class declaration statement iff it is [un]assigned before the local class declaration statement.
V is [un]assigned after a local variable declaration statement that contains no variable initializers iff it 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 it 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 it 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 iff it is [un]assigned before the local variable declaration statement.
V is definitely assigned before any variable initializer e other than the first one in the local variable declaration statement iff either V is definitely assigned after the variable initializer to the left of e or the initializer expression to the left of e is in the declarator that declares V.
V is definitely unassigned before any variable initializer e other than the first one in the local variable declaration statement iff V is definitely unassigned after the variable initializer to the left of e and the initializer expression to the left of e is not in the declarator that declares V.
V is [un]assigned after a labeled statement L:S (where L is a label) iff V is [un]assigned after S and V is [un]assigned before every break statement that may exit the labeled statement L:S.
V is [un]assigned before S iff V is [un]assigned before L:S.
V is [un]assigned after an expression statement e; iff it is [un]assigned after e.
V is [un]assigned before e iff it is [un]assigned before e;.
V is [un]assigned after if (e) S iff V is [un]assigned after S and V is [un]assigned after e when false.
V is [un]assigned before e iff V is [un]assigned before if (e) S.
V is [un]assigned before S iff V is [un]assigned after e when true.
V is [un]assigned after if (e) S else T iff V is [un]assigned after S and V is [un]assigned after T.
V is [un]assigned before e iff V is [un]assigned before if (e) S else T.
V is [un]assigned before T iff V is [un]assigned after e when false.
Either there is a default label 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 break statement that may exit the switch statement.
V is [un]assigned before the switch expression iff V is [un]assigned before the switch statement.
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 last block-statement of the preceding block-statement-group.
V is [un]assigned before any block-statement other than the first of any block-statement-group in the switch block iff V is [un]assigned after the last block-statement of the preceding block-statement-group.
V is [un]assigned after while (e) S iff V is [un]assigned after e when false and V is [un]assigned before every break statement for which the while statement is the break target.
V is definitely assigned before e iff V is definitely assigned before the while statement.
V is definitely unassigned before the while statement.
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 every continue statement for which the while statement is the continue target.
V is [un]assigned after do S while (e); iff V is [un]assigned after e when false and V is [un]assigned before every break statement for which the do statement is the break target.
V is definitely assigned before S iff V is definitely assigned before the do statement.
V is definitely unassigned before the do statement.
Assuming V is definitely unassigned before S, V is definitely unassigned after e when true.
V is [un]assigned before e iff V is [un]assigned after S and V is [un]assigned before every continue statement for which the do statement is the continue target.
Either a condition expression is not present or V is [un]assigned after the condition expression when false.
V is [un]assigned before every break statement for which the for statement is the break target.
V is [un]assigned before the initialization part of the for statement iff V is [un]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 unassigned after the initialization part of the for statement.
Assuming V is definitely unassigned before the condition part of the for statement, V is definitely unassigned after the contained statement.
Assuming V is definitely unassigned before the contained statement, V is definitely unassigned before every continue statement for which the for statement is the continue target.
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 for statement.
V is [un]assigned before the incrementation part of the for statement iff V is [un]assigned after the contained statement and V is [un]assigned before every continue statement for which the for statement is the continue target.
If the initialization part of the for statement 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.
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 E other than the first in the initialization part iff V is [un]assigned after the expression statement immediately preceding E.
If the incrementation part of the for statement is empty, then V is [un]assigned after the incrementation part iff V is [un]assigned before the incrementation part.
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 E other than the first in the incrementation part iff V is [un]assigned after the expression statement immediately preceding E.
By convention, we say that V is [un]assigned after any break, continue, return, or throw statement. 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, or throw statement never completes normally, it vacuously satisfies this notion.
In a return statement with an expression e or a throw statement with an expression e, V is [un]assigned before e iff V is [un]assigned before the return or throw statement.
V is [un]assigned after synchronized (e) S iff V is [un]assigned after S.
V is [un]assigned before e iff V is [un]assigned before the statement synchronized (e) S.
V is [un]assigned before S iff V is [un]assigned after e.
V is [un]assigned before the try block iff V is [un]assigned before the try statement.
V is definitely assigned before a catch block iff V is definitely assigned before the try block.
V is definitely unassigned before a catch block iff V is definitely unassigned after the try block and V is definitely unassigned before every return statement that belongs to the try block, every throw statement that belongs to the try block, every break statement that belongs to the try block and whose break target contains (or is) the try statement, and every continue statement that belongs to the try block and whose continue target contains the try statement.
V is [un]assigned after the try statement iff V is [un]assigned after the try block and V is [un]assigned after every catch block in the try statement.
V is definitely assigned after the try block and V is definitely assigned after every catch block in the try statement.
V is definitely assigned after the finally block.
V is definitely unassigned after a try statement iff V is definitely unassigned after the finally block.
V is definitely assigned before the finally block iff V is definitely assigned before the try statement.
V is definitely unassigned before the finally block iff V is definitely unassigned after the try block and V is definitely unassigned before every return statement that belongs to the try block, every throw statement that belongs to the try block, every break statement that belongs to the try block and whose break target contains (or is) the try statement, and every continue statement that belongs to the try block and whose continue target contains the try statement and V is definitely unassigned after every catch block of the try statement.
A formal parameter V of a method or constructor is definitely assigned (and moreover is not definitely unassigned) before the body of the method or constructor.
An exception parameter V of a catch clause is definitely assigned (and moreover is not definitely unassigned) before the body of the catch clause.
V is [un]assigned after an empty array initializer iff it is [un]assigned before the empty array initializer.
V is [un]assigned after a nonempty array initializer iff it 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 it is [un]assigned before the array initializer.
V is [un]assigned before any other variable initializer I of the array initializer iff it is [un]assigned after the variable initializer to the left of I in the array initializer.
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.
V is definitely assigned before a member type (§8.5, §9.5) declaration of C iff V is definitely assigned before the declaration of C.
V is definitely assigned before a static variable initializer 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. 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.
V is definitely unassigned (and moreover is not definitely assigned) before the leftmost static initializer or static variable initializer of C.
V is [un]assigned before a static initializer or static variable initializer of C other than the leftmost iff V is [un]assigned after the preceding static initializer or static variable initializer 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.
V is definitely assigned before an instance variable initializer 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.
V is definitely unassigned (and moreover is not definitely assigned) before the leftmost instance initializer 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.
V is definitely assigned (and moreover is not definitely unassigned) after an alternate constructor invocation.
V is definitely unassigned (and moreover is not definitely assigned) before an explicit or implicit superclass constructor invocation.
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.
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.

References: §15
 V. 
 V. 
 V.

 V.

 V.

 V.

 V.

 V.

 §16
 §9