Tuesday, October 8, 2013

Is the final variable really constant in Java?

My answer is no. Oh, it was a bold answer. Let's see why.

Constant is something that can not be changed. The final variable by definition is a variable that can be initialized once.

The difference is slight. If the variable can be initialized only once, how can we change it?

Let's think about objects. We can initialize a variable to the object. In fact, we initialize the variable to the address of the object in the main memory).

Recall how the objects are stored in Java. See the picture below.

In the variable name1 we store the address of the place in the main memory where the object is stored, which is 42 in the picture).

When we declare a variable as final and initialize it, we can not change the address after that, but we can change the object!

Let's look at an example.

class Main {

  public static final Test a = new Test("name"); //My final variable a

  public static void main(String args[]) {
    a._name = "I successfully changed the name!";
    System.out.println(a._name);
    //Output: "I successfully changed the name!"
  }
}

class Test {
  public String _name;

  public Test(String name) {
     _name = name;
  }
}

I created the static final variable a and initialized it to the new object new Test("name"); and then changed the name attribute of the object.

So, if we think about the address of this object, then the variable is constant. But if we expect to get the object that will not be changed, we are totally wrong!

If we want to prevent changing the _name attribute, we must add final keyword to the attribute. Then every "malefactor" which will try to change our field, will get compiler-error.

class Test {
  public final String _name;

  public Test(String name) {
     _name = name; //Compiler-error "cannot assign a value to final variable _name"
  }
}