Final Variables

February 10th, 2009

A question came up a few days ago regarding a change I made to the MessageQueue class in Spacewalk. I made the ACTIONS variable (of type Map) final. The reasons I did so refer to its use in a synchronized block, but that’s not the purpose of this blog.

Rather, this example brings up a good distinction I wish I had made in class. What exactly does it mean when a variable is defined as final?

A final variable means the variable can not be assigned a new value. When dealing with primitives, this is pretty simple: the variable can’t take on a different value.

1
private final int NUMBER = 5;

The variable NUMBER (the accepted convention for final variables is all caps) will never have a value other than 5. Nice and straightforward.

What about for objects? Is the following legal?

1
2
private final Person PERSON = new Person("Jason");
PERSON.setName("Jay");

Assuming the setName method doesn’t do anything weird, yes, the above is perfectly legal.

A final variable for an object refers to the object reference. In the above, the PERSON variable can never be pointed to a different Person instance (nor can it be set to null). Methods can still be executed on the object, some of which may change the state of the object. But the reference itself cannot be changed to refer to a different object.

In the Spacewalk example, we’re using a Map (more generally, a Collection). We can’t change the object referenced by ACTIONS, but we are free to manipulate the contents of the collection as necessary.

As a small side point, there is a way to lock the contents of a Collection. The Collections class (note the pluralization) contains a number of static methods for wrapping collections with new functionality. In this case, if we wanted to prevent the contents of the map from changing, we could have done something like:

1
2
3
Map alreadyPopulatedMap; // populated previously
Map neverChangeMe =
    <code></code>Collections.unmodifiableMap(alreadyPopulatedMap);

Comments are closed.