6

In JLS 8:

In 16:

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).

And we know that a final blank field cannot be accessed until it is definitely assigned.

So from 1 and 2 we deduce that we cannot access the final blank field with simple name qualified by this.

But

this code compiles fine:

public class Test {
   final int y;
   final int z = this.y;  
   { y = 1; 
   }
}

But it's error if we put final int z = y;

Where is the problem?

Community
  • 1
  • 1
Hicham Moustaid
  • 729
  • 6
  • 12
  • 2
    "*And we know that a final blank field cannot be accessed until it is definitely assigned*" not quite: http://ideone.com/04u069 we can assign it, `final` simply mean that it can be reassigned only once from its default value in constructor/initialization block. – Pshemo Apr 11 '15 at 22:04
  • I'm not sure, but maybe it has something to do with when the static initialization block is run? Or perhaps because on the JVM level this.y =/= to y as in it is treated differently by the JVM. I suspect it is something to do with the order things are initialized by java and JVM specific peculiarities. – Bassinator Apr 11 '15 at 22:08
  • 1
    You should have carried on with your example and checked out what value `z` now has. It might have led you to the answer :) – Ingo Bürk Apr 11 '15 at 22:09
  • @Ingo Okay, now I'm curious. What would z equal? And why? – Bassinator Apr 11 '15 at 22:09
  • My guess? z = null, whereas in the first bit z = an object reference. – Bassinator Apr 11 '15 at 22:11
  • 1
    @HCBPshenanigans `z` will be `0` as it is default value of `int` type field which will be given when `new` operator will finish its work and then will call proper constructor (which will initialize it to proper value). – Pshemo Apr 11 '15 at 22:11
  • 2
    @HCBPshenanigans As Pshemo said, it will be `0` since that's the default value (primitives cannot be `null`). By the way, Java 8 doesn't seem to compile this anymore. – Ingo Bürk Apr 11 '15 at 22:13
  • Ahhh.... Is this an autoboxing peculiarity? As in, the rawtype int has no default, but the conversion to a java object has a default of 0? – Bassinator Apr 11 '15 at 22:14
  • Actually, it sounds like I have it backwards. – Bassinator Apr 11 '15 at 22:14
  • I am not sure what you mean by: "As in, the rawtype int has no default". If you take a look at https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html you will find all default values for each type like `0` for `int`. – Pshemo Apr 11 '15 at 22:16
  • 2
    It fails to compile for me javac 1.8.0_40 on Fedora 21. - "Test.java:3: error: variable y might not have been initialized". – Sinkingpoint Apr 11 '15 at 22:20
  • @Quirliom Yes, but it compiles pre-Java 8. – Ingo Bürk Apr 11 '15 at 22:21
  • What version of Java? Doesn't compile on Java 8. http://ideone.com/Cd2szc – Radiodef Apr 11 '15 at 22:21
  • @Quirlion Correct me if I'm wrong, but don't different IDE's sometimes use slightly different compilers which could potentially have slightly different characteristics in grey areas not covered by the JLS? – Bassinator Apr 11 '15 at 22:22
  • 1
    @HCBPshenanigans Some IDEs use their own compiler (such as Eclipse), which have *behaviors* that deviate subtly from the specification (they have bugs). I have yet to find a "gray area" in the JLS. – Radiodef Apr 11 '15 at 22:25
  • 3
    @HCBPshenanigans See the duplicate. This isn't a grey area. Pre Java-7 this is correct behavior, >= Java-7, this is a bug. The JLS is written with very few, if any "grey areas". – Sinkingpoint Apr 11 '15 at 22:26
  • I'm not ashamed to admit that I'm not test-ready on my JLS knowledge haha. I'm a programmer, not a complier. But this is a very interesting language subtlety. – Bassinator Apr 11 '15 at 22:28
  • @HCBPshenanigans Agreed. I certainly learned something new today :) Something like this just never comes up in real life (to me anyway). It's interesting to see how this used to be defined behavior, then a bug and is now fixed in the compiler. – Ingo Bürk Apr 11 '15 at 22:29
  • I'm sure some evil CS professor out there somewhere is adding this to his test as we speak... – Bassinator Apr 11 '15 at 22:30
  • It doesn't compile on 1.8.0_31. Which version of java 8 are you using? – Nir Alfasi Apr 11 '15 at 22:33
  • 1
    @HCBPshenanigans You are not the only one to not like this kind of questions :) http://stackoverflow.com/questions/13778650/why-isnt-a-qualified-static-final-variable-allowed-in-a-static-initialization-b#comment19033557_13778650 – Pshemo Apr 11 '15 at 22:34
  • @Pshemo JLS says: 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. This is why your example is fine: – Hicham Moustaid Apr 11 '15 at 22:44
  • @alfasin OP is using *no* version of Java 8. Several people have remarked and explained now that this compiles only in Java <= 7. – Ingo Bürk Apr 11 '15 at 22:51
  • It compiles in Eclipse Luna – Hicham Moustaid Apr 11 '15 at 22:53
  • @IngoBürk it doesn't compile on Java 1.7.0_75 – Nir Alfasi Apr 11 '15 at 23:04
  • @alfasin It's a compiler bug, so it will be compiler implementation specific. – Ingo Bürk Apr 11 '15 at 23:12
  • @IngoBürk I guess I misunderstood when you said: "now that this compiles only in Java <= 7" - you probably meant that it compiles only in specific versions which are <= 7 (not on *all* of them). – Nir Alfasi Apr 11 '15 at 23:31

0 Answers0