Given the following examples:
class A {
public static void main(String[] args) {
int n=5;
int k;
while(n<6) {
k=5;
break;
}
System.out.println(k);
}
}
and:
class B {
public static void main(String[] args) {
int k;
while(true) {
k=5;
break;
}
System.out.println(k);
}
}
I know that the first example won't run properly because k hasn't been definitely assigned; while the second example can run through.
I also read the rough explanations given to a large number of examples in the earlier part of Chapter 16 of the JLS.
However, when I tried to use the formal definite assignment rules to judge these two examples, I was unable to make an accurate judgment on them.
The rules I'm using are from the JLS:
16.2.10 The while statement
•
V
is [un]assigned afterwhile (e) S
(§14.12) iffV
is [un]assigned aftere
when false andV
is [un]assigned before every break statement for which the while statement is the break target.•
V
is definitely assigned beforee
iffV
is definitely assigned before the while statement.•
V
is definitely unassigned beforee
iff all of the following are true: –V
is definitely unassigned before the while statement. – AssumingV
is definitely unassigned beforee
,V
is definitely unassigned afterS
. – AssumingV
is definitely unassigned beforee
,V
is definitely unassigned before every continue statement for which the while statement is the continue target.•
V
is [un]assigned beforeS
iffV
is [un]assigned aftere
when true.
For example, when I'm judging the second example, if e
is true, it seems that only the last rule can be applied, but this rule doesn't seem to be able to determine that k
has been definitely assigned.
So, how can we determine whether the above examples have been definitely assigned according to the specifications?Thank you for reading and answering.
Out of all the bullet points, only the first one is the only relevant one, in order to determine whether System.out.println(k);
at the end is valid.
V is [un]assigned after while (e) S (§14.12) 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.
The phrases "[un]assigned after e when true" and "[un]assigned after e when false" are special technical terms defined towards the start of the chapter. "[un]assigned after e
when false" can still be a true statement even if the value of e
is true.
From 16.1.1,
V is [un]assigned after any constant expression (§15.29) whose value is
true
when false.
So in the second example, both of the following holds:
k
is unassigned after true
when falsek
is assigned after true
when falseThe point of this clause is to capture the idea of vacuous truth.
Obviously, it is also the case that k
is definitely assigned before every break statement, so we can conclude that k
is definitely assigned after the while statement, and k
is not definitely unassigned after the while statement.
For the first example, "k
is unassigned after n < 6
when false" holds, because k
is unassigned before n < 6
. "k
is assigned after n < 6
when false" does not hold. See the sections 16.1.7 and 16.1.10 for more details. Therefore, k
is not definitely assigned after the while statement, and also not definitely unassigned after the while statement.