Assigning a value to final instance variable using this keyword

I wanted to understand what am missing in the usage of final variable. I tried googling a lot about this strange (to me at least) behavior, and would love to know what happens behind the scenes.

Java Specification says: A variable can be declared final. A final variable may only be assigned to once. Declaring a variable > final can serve as useful documentation that its value will not change and can help avoid programming > errors.

It is a compile-time error if a final variable is assigned to unless it is definitely unassigned (ยง16) > immediately prior to the assignment.

A blank final is a final variable whose declaration lacks an initializer.


Now consider the following code:

public class Sample {
    private final int a;
    private final Object object1; // compile error that object1 is not initialized
    private final Object object2 = null;

    public Sample(int value) {
        System.out.println(this.a);
        a = value;
        System.out.println(this.a);
        object2 = new Object(); // Compile error that it shouldn't change
    }
}

Below are my observations:

  • In line 2 public final int a the JVM will assign a default value of 0 to a
  • Which is why the first print statement in the Constructor prints value "0"
  • Then we are trying to modify the default value to a "value" (a=value) that is passed to the constructor
  • It allows to change the value, and then from the next assignment the compiler will give an error.
  • While in the case of Objects private final Object object1 it gives a compile time error that object1 is not initialized. Though by default JVM assigns a "null" value for instance members by default.
  • Once a value for the object is assigned private final Object object2=null then it works pretty much as expected.

Now can someone answer, why the compiler behaves differently with the default assignments to primitives and objects when final keyword is used?

In case if you feel if this a dumb question am sorry, but I request you to point to a source where I can get the answer.


Thanks
Sharath

Jon Skeet
people
quotationmark

In line 2 public final int a the JVM will assign a default value of 0 to a

That's what the JVM does. That's not what the compiler does - it's not an assignment within the source code. It's just the value the variable has before it's assigned any other value.

The JLS doesn't say that you can't observe the value of a final variable changing within a constructor. It says that you must assign to a final variable exactly once. That's exactly the case for a - the only assignment to it is within the constructor, so it's fine.

There's no difference between primitives and classes here - if you explicitly assign a value of 0 to a in the field declaration, you'll see the same error when you try to assign to a within the constructor.

people

See more on this question at Stackoverflow