As far as I can tell there is nothing special here, is just classical constructor chaining and polymorphism applied to virtual method invocations.
When you instantiate your anonymous class, it will automatically invoke its default constructor (which is automatically given by the compiler), before its default constructor succeeds it must first invoke its parent class default constructor, which in turn will invoke the init()
method, which, since it has been overridden by your anonymous class, polymorphically, ends up calling the init
method in the child class, which initializes the model to your SubModel
instance.
Joshua Bloch has a few interesting arguments against this pattern in his famous book Effective Java, in the section "Item 17: Design and document for inheritance or else prohibit" he wrote:
“There are a few more restrictions that a class must obey to allow
inheritance. Constructors must not invoke overridable methods,
directly or indirectly. If you violate this rule, program failure will
result. The superclass constructor runs before the subclass
constructor, so the overriding method in the subclass will get invoked
before the subclass constructor has run. If the overriding method
depends on any initialization performed by the subclass constructor,
the method will not behave as expected. To make this concrete, here's
a class that violates this rule:”
He then proceeds to give an example which you would do well to study:
“Here's a subclass that overrides the overrideMe
, method which is
erroneously invoked by Super
's sole constructor:”
public class Super {
// Broken - constructor invokes an overridable method
public Super() {
overrideMe();
}
public void overrideMe() {
}
}
public final class Sub extends Super {
private final Date date; // Blank final, set by constructor
Sub() {
date = new Date();
}
// Overriding method invoked by superclass constructor
@Override public void overrideMe() {
System.out.println(date);
}
public static void main(String[] args) {
Sub sub = new Sub();
sub.overrideMe();
}
}
“You might expect this program to print out the date twice, but it
prints out null the first time, because the overrideMe
method is
invoked by the Super constructor before the Sub
constructor has a
chance to initialize the date field. Note that this program observes a
final field in two different states! Note also that if overrideMe
had
invoked any method on date
, the invocation would have thrown a
NullPointerException
when the Super
constructor invoked overrideMe
.
The only reason this program doesn't throw a NullPointerException
as
it stands is that the println
method has special provisions for
dealing with a null argument.”
So, as you can see, and as Joshua Bloch explained so well, the risks lurk in the shadows: in the possibilities of what you can do in the overridden method, where you have license to touch instance variables that the constructor chain has not yet had a chance to initialize. The point is that you should not be allowed to touch the object state until it has been fully initialized by the constructor chain.
You might say that in your particular case that does not happen, since you are not illegally altering state and your overridden method is protected, not public, but the problem is that any person touching this code needs a very clear understanding of all these things happening under the hood, happening in places other than your current code. During maintenance it is easy to make a serious mistake, particularly when you or some other developer, comes back here to make changes, possibly months or even years after this was originally defined, and having lost context of all these dangers somebody introduces a bug that will be really hard to find and fix.