I read this question about how to do Double-checked locking:
// Double-check idiom for lazy initialization of instance fields
private volatile FieldType fiel
Quoting The "Double-Checked Locking is Broken" Declaration mentioned by @Kicsi, the very last section is:
Double-Checked Locking Immutable Objects
If Helper is an immutable object, such that all of the fields of Helper are final, then double-checked locking will work without having to use volatile fields. The idea is that a reference to an immutable object (such as a String or an Integer) should behave in much the same way as an int or float; reading and writing references to immutable objects are atomic.
(emphasis is mine)
Since FieldHolder is immutable, you indeed don't need the volatile keyword: other threads will always see a properly-initialized FieldHolder. As far as I understand it, the FieldType will thus always be initialized before it can be accessed from other threads through FieldHolder.
However, proper synchronization remains necessary if FieldType is not immutable. By consequent I'm not sure you would have much benefit from avoiding the volatile keyword.
If it is immutable though, then you don't need the FieldHolder at all, following the above quotation.