[java] How does the "final" keyword in Java work? (I can still modify an object.)

The final keyword indicates that a variable may only be initialized once. In your code you are only performing one initialization of final so the terms are satisfied. This statement performs the lone initialization of foo. Note that final != immutable, it only means that the reference cannot change.

foo = new ArrayList();

When you declare foo as static final the variable must be initialized when the class is loaded and cannot rely on instantiation (aka call to constructor) to initialize foo since static fields must be available without an instance of a class. There is no guarantee that the constructor will have been called prior to using the static field.

When you execute your method under the static final scenario the Test class is loaded prior to instantiating t at this time there is no instantiation of foo meaning it has not been initialized so foo is set to the default for all objects which is null. At this point I assume your code throws a NullPointerException when you attempt to add an item to the list.