In addition to documenting your intent clearly and making your code easier to understand and maintain, a final
modifier provides some important assurances in a multi-threaded application.
While I'm not sure if it's guaranteed by the Servlet specification, it seems that in practice, servlet engines should use some memory barrier that will ensure that the internal state of a new servlet instance is visible to all of the threads that will use it to process servlet requests. This is called "safe publication."
However, in general, this is not the case. What you describe as "Option 2" is "effective immutability." The object has a field that isn't final
, but doesn't allow modification of that field after construction or some initialization step. But, if other threads access this object without going through a memory barrier, they might not see the value assigned to that field by the initializing thread—even if this field was set in the object's constructor!
A value assigned during object construction to a final
field, however, is guaranteed to be visible to all other threads, even if the object itself is not "safely published."