If you make foo
static, you must initialize it in the class constructor (or inline where you define it) like the following examples.
Class constructor (not instance):
private static final List foo;
static
{
foo = new ArrayList();
}
Inline:
private static final List foo = new ArrayList();
The problem here is not how the final
modifier works, but rather how the static
modifier works.
The final
modifier enforces an initialization of your reference by the time the call to your constructor completes (i.e. you must initialize it in the constructor).
When you initialize an attribute in-line, it gets initialized before the code you have defined for the constructor is run, so you get the following outcomes:
- if
foo
is static
, foo = new ArrayList()
will be executed before the static{}
constructor you have defined for your class is executed
- if
foo
is not static
, foo = new ArrayList()
will be executed before your constructor is run
When you do not initilize an attribute in-line, the final
modifier enforces that you initialize it and that you must do so in the constructor. If you also have a static
modifier, the constructor you will have to initialize the attribute in is the class' initialization block : static{}
.
The error you get in your code is from the fact that static{}
is run when the class is loaded, before the time you instantiate an object of that class. Thus, you will have not initialized foo
when the class is created.
Think of the static{}
block as a constructor for an object of type Class
. This is where you must do the initialization of your static final
class attributes (if not done inline).
Side note:
The final
modifier assures const-ness only for primitive types and references.
When you declare a final
object, what you get is a final
reference to that object, but the object itself is not constant.
What you are really achieving when declaring a final
attribute is that, once you declare an object for your specific purpose (like the final List
that you have declared), that and only that object will be used for that purpose: you will not be able to change List foo
to another List
, but you can still alter your List
by adding/removing items (the List
you are using will be the same, only with its contents altered).