Does the Java compiler allow access to an uninitialized empty final field using the 'this' keyword? This is mistake?

I wrote this piece of code, and it seems that the compiler allows you to access the uninitialized empty final field when accessed using the 'this' keyword:

public class TestClass { public final int value1; public int value2; TestClass(int value) { value2 = 2 + this.value1; // access final field using 'this' before initialization gives no compiler error //value2 = 2 + value1; // uncomment it gives compile time error - variable value1 might not have been initialized value1 = value; } public static void main(String args[]) { TestClass tc = new TestClass(10); System.out.println("\nTestClass Values : value1 = " + tc.value1 + " , value2 = " + tc.value2); } } 

I tried to collect it on 1.5, 1.6 and 1.7 and got the same result in all three of them.

For me, this looks like a compiler error, because the compiler should throw an error in this case, but with the keyword 'this' it is not, and therefore creates an area of ​​coding error, since it will go unnoticed by the programmer, since compilation or launch a time error will be triggered.

SEVERAL ITEMS WHY IT IS NOT A DUPLICATE
- all answers explain how it works and what JLS says, well, but should my real intention here be resolved in the first place?
- my question here is more from the point of view of the programmer, not the semantics of the language

+8
java initialization final javac
Jun 16 '14 at 9:14
source share
3 answers

It's not a mistake. This is a feature for Java Specification 1.6 and below.

The final field can be obtained in any part of the code. There are no restrictions on this.

The only limitation in the case of final is that it must be initialized before the class is instantiated.

When you use this , you express that it is an element of the object that is being built.

Since specification 1.7 is due to a change , we can say that this is a mistake in some compiler implementation.

But with 1.8, the code will this.value1 the same error for this.value1 or value1 .

+1
Jun 16 '14 at 9:19
source share

Java ints has a default value of 0, so even if you did not initialize it, the compiler still assigned the value 0.

Fields declared but not initialized will be set by a reasonable default compiler. Generally speaking, this default value will be zero or zero, depending on the data type.

Source: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Note that this does not apply to local variables, only field variables have a default value.

+1
Jun 16 '14 at 9:18
source share

I used the following code

 public class HelloWorld { public final int value1; public int value2; public HelloWorld(int value){ System.out.println(this.value1); System.out.println(this.value2); value1 = value; } public static void main(String args[]) { } } 

and the generated bytecode is

 Compiled from "HelloWorld.java" public class test.HelloWorld extends java.lang.Object{ public final int value1; public int value2; public test.HelloWorld(int); Code: 0: aload_0 1: invokespecial #11; //Method java/lang/Object."<init>":()V 4: getstatic #14; //Field java/lang/System.out:Ljava/io/PrintStream; 7: aload_0 8: getfield #20; //Field value1:I 11: invokevirtual #22; //Method java/io/PrintStream.println:(I)V 14: aload_0 15: iload_1 16: putfield #20; //Field value1:I 19: return public static void main(java.lang.String[]); Code: 0: return } 

If you notice that the JVM makes a getstatic call in the case of final and getfield in the case of a regular instance variable. Also now, if you look at the specifications for getstatic , it says

If the field is successfully resolved, the class or interface that declared the allowed field is initialized (§5.5) if this class or interface has not yet been initialized.

So, if you use this with a final variable, then it initializes it. this.value1 will not be initialized, not value1 , which is final. You still need to initialize it before use.

0
Jun 16 '14 at 9:38
source share



All Articles