All these facts violate my intuition of what I thought about the constructor.
They should not. The designer does exactly what you think.
1: uninitialized objects can be skipped by sharing this
3: Uninitialized objects may leak into another thread before they are fully built.
The problem with this leak, the start of threads in the constructor and saving the newly created object, where several threads access it without synchronization, is all the problems associated with reordering the initialization of non-competitive (and non-volatile) ones. But the initialization code is still executed by the constructor. The stream that built the object fully sees the object. This applies to when these changes are visible in other threads that are not guaranteed by the language definition.
You may be tempted to say that you know that the constructor of X is finished and you have a valid object, but this is not true if you pass X to another thread - the other thread may see an uninitialized version (that is, what you just said no different from factory call guarantees).
It is right. It is also correct that if you have an unsynchronized object and you mutate it in one thread, other threads may or may not see the mutation. This is the nature of threaded programming. Even designers are not protected from the need to correctly synchronize objects.
2: uninitialized objects can be skipped by a subclass receiving it from the finalizer
This document is about finalizers and improper access to an object after garbage collection. When hacking subclasses and finalizers, you can create an object that was not properly constructed, but this is a serious hack for this. For me, this does not somehow challenge what the constructor does. Instead, it demonstrates the sophistication of a modern, mature, JVM. The document also shows how you can write your code to get around this hack.
What properties are guaranteed by designers in Java?
By definition, the constructor:
- Allocates space for an object.
- Sets all instance variables in the object by default. This includes instance variables in object superclasses.
- Assigns parameter variables to an object.
- handles any explicit or implicit constructor call (calling this () or super () in the constructor).
- Initializes variables in the class.
- Performs the remainder of the constructor.
From the point of view of your 3 problems, # 1 and # 3, again, about when the initialization of non-final and non-volatile fields is visible by flows other than those that built the object. This visibility without synchronization is not guaranteed.
Problem # 2 shows a mechanism in which, if an exception occurs during constructor execution, you can override the finalize method to get an incorrectly constructed object. Constructor points 1-5 have occurred. With hacking, you can get around part 6. I think it’s in the eye of the beholder if it challenges the identity of the constructor.