Card 08/ 10

GotchaDifficulty: Advanced1 min

What final Stops, on a Class, a Method and a Field

You extend a class from a library and the build fails. You override a method and the build fails. You assign to a field in a second method and the build fails. One keyword, three different messages.

What final prevents in each of the three places it can appear
Written onPreventsStill allowed
A classAnything extending itCreating instances, calling everything on it
A methodA subclass overriding itCalling it, and overloading the name
A fieldAssigning to it after it is setChanging the object it points at
java
final class Money { }

class Account {
    final List<String> history = new ArrayList<>();

    void log(String line) {
        history.add(line);          // fine
        history = new ArrayList<>(); // will not compile
    }
}

The last row is the one that surprises people. final on a reference field freezes the address, not the object at that address. Line 7 changes the list and is legal; line 8 tries to point the field somewhere else and is not.

Reach for final on fields by default — it says the value is decided once, and the compiler will tell you if any path fails to set it. Reach for it on classes and methods deliberately, because it is a promise to everyone that this behaviour will never be replaced.