Java Reference
In-Depth Information
17.5.
final
Field Semantics
Fields declared final are initialized once, but never changed under normal circumstances.
The detailed semantics of
final
fields are somewhat different from those of normal fields.
In particular, compilers have a great deal of freedom to move reads of
final
fields across
synchronization barriers and calls to arbitrary or unknown methods. Correspondingly, com-
pilers are allowed to keep the value of a
final
field cached in a register and not reload it from
memory in situations where a non-
final
field would have to be reloaded.
final
fields also allow programmers to implement thread-safe immutable objects without
synchronization. A thread-safe immutable object is seen as immutable by all threads, even
if a data race is used to pass references to the immutable object between threads. This can
provide safety guarantees against misuse of an immutable class by incorrect or malicious
code.
final
fields must be used correctly to provide a guarantee of immutability.
An object is considered to be
completely initialized
when its constructor finishes. A thread
that can only see a reference to an object after that object has been completely initialized is
guaranteed to see the correctly initialized values for that object's
final
fields.
The usage model for
final
fields is a simple one: Set the
final
fields for an object in that ob-
ject's constructor; and do not write a reference to the object being constructed in a place
where another thread can see it before the object's constructor is finished. If this is fol-
lowed, then when the object is seen by another thread, that thread will always see the cor-
rectly constructed version of that object's
final
fields. It will also see versions of any object
or array referenced by those
final
fields that are at least as up-to-date as the
final
fields are.
Example 17.5-1.
final
Fields In The Java Memory Model
The program below illustrates how
final
fields compare to normal fields.
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}