18 July 2007

java final vars != magic constant creator

In general, a lot of us tend to use the final keyword alongside public and static. Quite often too, we use it to declare a constant, perhaps a String, or int value. But, does the final keyword cause the variable to become a constant?

public class FinalExample {

public static final String CONSTANT =
"I can never change!";

}


Alright. We've got a constant. Let's try and make it not so constant:



public class FinalExample {

public static final String CONSTANT =
"I can never change!";

public static void main (String[] args) {
CONSTANT = "I can always change";
}

}

$ javac *.java
FinalExample.java:7: cannot assign a value to final variable CONSTANT
CONSTANT = "I can always change";
^
1 error

So the compiler enforces that you can't try to assign a value to a final variable. It didn't say anything about keeping it constant (that was the variable name). So, let's try and switch this up:

public class FinalExample {

public static final String[] CONSTANT_ARRAY =
{"I", "can", "never", "change"};

public static void main (String[] args) {
for (int x=0; x<CONSTANT_ARRAY.length; x++)
System.out.print(CONSTANT_ARRAY[x] + " ");
System.out.println();
}

}

$ java FinalExample
I can never change


This compiles and runs fine with the output as above. Let's try and break this.


public class FinalExample {

public static final String[] CONSTANT_ARRAY =
{"I", "can", "never", "change"};

public static void main (String[] args) {
CONSTANT_ARRAY[2] = "always";
for (int x=0; x<CONSTANT_ARRAY.length; x++)
System.out.print(CONSTANT_ARRAY[x] + " ");
System.out.println();
}

}

$ java FinalExample
I can always change


So, we just changed a final declared variable. Ok, let's try and change it a little differently.

public class FinalExample {

public static final String[] CONSTANT_ARRAY =
{"I", "can", "never", "change"};

public static void main (String[] args) {
CONSTANT_ARRAY =
{"I", "can", "always", "change"};
}

}

$ javac *.java
FinalExample.java:6: illegal start of expression
CONSTANT_ARRAY = {"I", "can", "always", "change"};
^
1 error


So, what gives?

  • Final declarations ensure that a declared variable is never re-assigned to something else. Once you go: final something = something, you don't get to say something = something_else later on.

  • In the event that your object is mutable- ie: can be changed, you are out of luck in trying to make it a constant using final. So, something like a Calendar object which has setters on it to change its value won't hold some magical constantness by being declared as final. This applies to array elements too, as demonstrated above.