How can this be passed to other classes, when Parent is being created as it's constructor is being executed?
The execution of new X(), in pseudocode:
void createInstance {
int totalSize = SIZE_OF_TYPE_REF + SIZE_OF_IDENTITY;
for (Field f : type.allInstanceFieldsOfThisAndSuperTypes()) {
totalSize += f.sizeInBytes();
}
ptr = malloc(totalSize);
ptr[0-7] = type.ref;
ptr[8-15] = randomId();
invokeConstructor(makeObjectOutOf(ptr));
}
But this takes some liberties; the spec is not nearly as specific as that.
The point is - the answer to your question is rather simple: The JVM makes the object first and then treats the constructor as a method that gets to toy with it first. At the JVM level, it's incorrect to think that the end result of a constructor is the creation of a single instance. No, thats how they start. The end result of a constructor is that the instance already created when it started is now in a valid state.
Yes, the logical conclusion you seem to sort of draw (given the somewhat incredulous tone of your question) is indeed the bizarre but correct conclusion:
Instances exist as of the start of the constructor but aren't actually semantically guaranteed in valid state until the end; nevertheless they exist and this can be passed around. Invalid state and all. It is entirely up to the programmer to take this foot gun and handle it with great care.
This is fairly well known. Various linting tools will outright tell you that you are 'leaking this', and tell you to cut it out. The JVM spec itself is starting to have an opinion, scans for leaking your this, and has to downshift to less efficient paths, in order to fulfill certain guarantees the Java Memory Model makes about the visibility of updates to final fields.
We can trivially take this footgun and deal some serious damage, your example is in that sense barely cracking the top of this particular iceberg, so to speak:
class Person {
private final String name;
Person(String name) {
Greeter.greet(this);
this.name = name;
}
public String getName() { return this.name; }
}
class Greeter {
static void greet(Person p) {
System.out.println("Hello, " + p.getName() + "!");
}
public static void main(String[] args) {
Person p = new Person("Aizaz");
Greeter.greet(p);
}
}
Toss that in a file, compile it, and then run java Greeter and out comes:
Hello, null!
Hello, Aizaz!
What the heck? We have a final field and only one instance, thus we could only possibly observe that field having one value. Except.. we see two of em. a null and a value. When compiling we got no warnings at all!
That's the foot gun. It went off.
Fortunately it's easy to know when this happens: Anytime that you leak 'this'. This is done either if you refer to this in a constructor which you should not do except for this.fieldName = shadowedFieldName;), or if you invoke an instance method in your constructor which you should never do. If you want your constructor to have helpers, make em static, which avoids this messy situation. As mentioned, various linter tools can help you out and will flag any such code with a warning, because both of these situations are things that basic rules-based code analysis can trivially find with a 100% accuracy rate (no false positives and no false negatives).
Q2 Is this some kind of design pattern?
Sure, well, we'd have to get into philosophy. What is a 'design pattern'?
It's somewhat common. It's also a bad idea. You should not write your code like this, because of the footgun nature of it. It's easy enough to spot this leakage in a constructor. It's not at all easy to intentionally do so, put the onus on whatever you leak the this to not to touch the foot gun aspects of it, and then attempt to put rules into place such as with linter tools to police that. Generally you use the linter tool to lint the easy, 100% accurately lintable thing and deal with the fallout.
But this gets to the underlying problem
The abstract structure that you have created here is the doubly linked tree structure. You have nodes that have refs to their children, and you want the children to have refs back to their parents.
Whilst this is a commonly cooked up solution to various designs, you should reconsider. For example, javac itself does not do this; its parser turns java source files into tree structures (CompilationUnit, which contains TypeDefinition objects, those contain TypeMember objects (which can be FieldDeclaration, MethodDeclaration, ConstructorDeclaration, and TypeDefinitions, amongst other things), those contain Parameter objects and a Body which in turns contains a bunch of Statement objects - hopefully it is not difficult to envision how source files are turned into complicated tree structures.
In the javac source code, nodes do not have a ref to their parents.
Whatever job requires you to 'travel' "up" the tree, find another way to do it. For example, invert the control structure. Alternatively, have a separate object that represents the entire tree as a whole, and it has a ref to the root node. It can be asked to travel up (so a child instance does not know its parent, but you can ask the tree as a whole 'give me the parent of child child) and it does know.
Alternatively, have the concept of parent be a settable thing. It's not a final field, and post construction a child starts off as parent-less. This means your object goes through multiple phases of construction; after phase 1 different rules hold than after phase 2 (phase 1 is the constructor, phase 2 is the thing where the parent 'marks' itself as parent of that object). You can attempt to then document these lifecycle processes and in that way attempt to ensure (with little help from the compiler) that e.g. child objects are never leaked to beyond the package until they hit some final phase. If that's not possible you can even make 'which phase are we in' part of the public API - have the class def have a 'getState()' method that returns an enum representing where we're at, and then document that various methods cannot be called unless certain states have been reached.
This is not a particularly nice design and runs afoul of various philosophical treatises on how OO 'should be', but in the end, how it 'should be' is scientifically speaking mostly drivel: IT has very little rigorous scientifically tested hypotheses, it's truly the weakest of all the 'sciences'. If it works, it works. If it works but the maintenance headache seems unduly ridiculous given the scope of the project and teaching new team members the ropes takes ages, and your tests are convoluted messes - that might be a sign your design is insufficient. I'd put more stock in that than abstract philosophical 'rules' such as Liskov's substitution principle or "SOLID design" ^1.
Point is, 'how to represent doubly-linked tree structures in OO / java' is a complicated question that is beyond the scope of SO for a complete treatise; it's more the domain of 40-page papers and veers far too much into opinion to actually 'answer'; hence I have merely provided the context.
[1] Dear reader, you may be thinking: What heresy is this?? Liskov and SOLID are fantastic; in some distant past I did not apply them properly and my code was a mess, since I learned, I apply it rigorously and my code is much easier to maintain! Ah, but therein lies the rub: You, dear reader, have experience. From my experience, attempting to apply these principles when you have no idea what they truly mean due to lack of experience - that's just a formula for truly brain-twisting lunacy. Cargo culting writ large. So please do not read this paragraph a 'Liskov and SOLID are lies'. It's more 'Liskov and SOLID are not useful tools to teach. They are useful tools only to describe and neatly file away the lessons you already learned the hard way'.
thisin the constructor, see stackoverflow.com/questions/9851813/… and all related questions.null/0/0.0/falseParent,BrotherandSisterare only subclasses ofObject, but neither is a subclass of the others; 2) also be aware that the constructor, despite its name, is not really constructingthis, it is only initializing the instance -thisis created by thenewstatement before executing the constructor (basically a pointer/reference to some memory location)thisis created by thenewstatement, then how this reference is present whennew Brother(this)is being executed in the constructor which is not complete yet to providethisto thenewstatement.