Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>After a bunch of spec-reading and thought, I've concluded that:</p> <p>In a Java 5 or Java 6 compiler, this is correct behavior. <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/defAssign.html" rel="noreferrer">Chapter 16 "Definite Assignment of <em>The Java Language Specification</em>, Third Edition</a> says:</p> <blockquote> <p>Each local variable <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/statements.html#5920" rel="noreferrer">(§14.4)</a> and every blank <code>final</code> <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#10931" rel="noreferrer">(§4.12.4)</a> field <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#35962" rel="noreferrer">(§8.3.1.2)</a> must have a <em>definitely assigned</em> value when any access of its value occurs. An access to its value consists of <strong>the simple name of the variable</strong> occurring anywhere in an expression except as the left-hand operand of the simple assignment operator <code>=</code>.</p> </blockquote> <p>(emphasis mine). So in the expression <code>2 * this.x</code>, the <code>this.x</code> part is <em>not</em> considered an "access of [<code>x</code>'s] value" (and therefore is not subject to the rules of definite assignment), because <code>this.x</code> is not the simple name of the instance variable <code>x</code>. (N.B. the rule for when definite assignment occurs, in the paragraph after the above-quoted text, <em>does</em> allow something like <code>this.x = 3</code>, and considers <code>x</code> to be definitely assigned thereafter; it's only the rule for accesses that doesn't count <code>this.x</code>.) Note that the value of <code>this.x</code> in this case will be zero, per <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5.2" rel="noreferrer">&sect;17.5.2</a>.</p> <p>In a Java 7 compiler, this is a compiler bug, but an understandable one. <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html" rel="noreferrer">Chapter 16 "Definite Assignment" of the <em>Java Language Specification</em>, Java 7 SE Edition</a> says:</p> <blockquote> <p>Each local variable (<a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.4" rel="noreferrer">§14.4</a>) and every blank <code>final</code> field (<a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4" rel="noreferrer">§4.12.4</a>, <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.2" rel="noreferrer">§8.3.1.2</a>) must have a <em>definitely assigned</em> value when any access of its value occurs.</p> <p>An access to its value consists of the simple name of the variable <strong>(or, for a field, the simple name of the field qualified by <code>this</code>)</strong> occurring anywhere in an expression except as the left-hand operand of the simple assignment operator <code>=</code> (<a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.1" rel="noreferrer">§15.26.1</a>).</p> </blockquote> <p>(emphasis mine). So in the expression <code>2 * this.x</code>, the <code>this.x</code> part <em>should</em> be considered an "access to [<code>x</code>'s] value", and <em>should</em> give a compile error.</p> <p>But you didn't ask <em>whether</em> the first one <em>should</em> compile, you asked <em>why</em> it <em>does</em> compile (in some compilers). This is necessarily speculative, but I'll make two guesses:</p> <ol> <li>Most Java 7 compilers were written by modifying Java 6 compilers. Some compiler-writers may not have noticed this change. Furthermore, many Java-7 compilers and IDEs still support Java 6, and some compiler-writers may not have felt motivated to specifically reject something in Java-7 mode that they accept in Java-6 mode.</li> <li>The new Java 7 behavior is strangely inconsistent. Something like <code>(false ? null : this).x</code> is still allowed, and for that matter, even <code>(this).x</code> is still allowed; it's only the specific token-sequence <code>this</code> plus <code>.</code> plus the field-name that's affected by this change. Granted, such an inconsistency already existed on the left-hand side of an assignment statement (we can write <code>this.x = 3</code>, but not <code>(this).x = 3</code>), but that's more readily understandable: it's accepting <code>this.x = 3</code> as a special permitted case of the otherwise forbidden construction <code>obj.x = 3</code>. It makes sense to allow that. But I don't think it makes sense to reject <code>2 * this.x</code> as a special forbidden case of the otherwise permitted construction <code>2 * obj.x</code>, given that (1) this special forbidden case is easily worked around by adding parentheses, that (2) this special forbidden case was allowed in previous versions of the language, and that (3) we still need the special rule whereby <code>final</code> fields have their default values (e.g. <code>0</code> for an <code>int</code>) until they're initialized, both because of cases like <code>(this).x</code>, and because of cases like <code>this.foo()</code> where <code>foo()</code> is a method that accesses <code>x</code>. So some compiler-writers may not have felt motivated to make this inconsistent change.</li> </ol> <p>Either of these would be surprising &mdash; I assume that compiler-writers had detailed information about every single change to the spec, and in my experience Java compilers are usually pretty good about sticking to the spec exactly (unlike some languages, where every compiler has its own dialect) &mdash; but, well, <em>something</em> happened, and the above are my only two guesses.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload