What you are saying is true.
Marking a field as final forces the compiler to complete initialization of the field before the constructor completes. There is no such guarantee however for non-final fields. This might seem weird, however there are many things done by the compiler and JVM for optimization purposes such as reordering instructions, that cause such stuff to occur.
The final keyword has many more benefits. From the Java Concurecncy in Practice:
Final fields can’t be modified (although the objects they refer to can be modified if they are mutable), but they
also have special semantics under the Java Memory Model. It is the use of final fields that makes possible the guarantee
of initialization safety (see Section 3.5.2) that lets immutable objects be freely accessed and shared without
synchronization.
The Books says then:
To publish an object safely, both the reference to the object and the object’s state must be made visible to other
threads at the same time. A properly constructed object can be safely published by:
- Initializing an object reference from a static initializer;
- Storing a reference to it into a volatile field or AtomicReference;
- Storing a reference to it into a final field of a properly constructed object; or
- Storing a reference to it into a field that is properly guarded by a lock.