このコンスタレーションは、優れた OO 設計以外のルールに違反するものではありません。次の例に示すように、コンストラクターが呼び出される前に B のすべてのフィールドが初期化されるため、Java はこの場合に備えています。
public class A {
int aMember;
public static final void main(String[] args) {
new B();
}
A() {
B b = (B) this;
System.out.println("in A(), before b.bMember has been set here, b.bMember = " + b.bMember);
System.out.println("in A(), before this.aMember has been set here, this.aMember = " + this.aMember);
this.aMember = 5;
b.bMember = 1; // will be overwritten in B()
System.out.println("in A(), after b.bMember has been set here, b.bMember = " + b.bMember);
System.out.println("in A(), after this.aMember has been set here, this.aMember = " + this.aMember);
}
}
--
public class B extends A {
int bMember;
B() {
super(); // invokes A()
System.out.println("in B(), before this.bMember has been set here, this.bMember = " + this.bMember);
this.bMember = 6;
System.out.println("in B(), after this.bMember has been set here, this.bMember = " + this.bMember);
}
}
これは以下を出力します:
in A(), before b.bMember has been set here, b.bMember = 0
in A(), before this.aMember has been set here, this.aMember = 0
in A(), after b.bMember has been set here, b.bMember = 1
in A(), after this.aMember has been set here, this.aMember = 5
in B(), before this.bMember has been set here, this.bMember = 1
in B(), after this.bMember has been set here, this.bMember = 6
つまり、A() では、B のメンバー変数は、設定される前は A のメンバー変数と同じ状態にあるだけです。どちらもデフォルト (int の場合は 0、ブール値の場合は false、オブジェクトの場合は null など) に初期化されており、使用できます。重大な落とし穴は、B のメンバー変数を A() で設定できるが、B 自身のコンストラクターによって上書きできることです。これは非常に直感に反します。
シンプルかつ明確に表現されているため、私はこの質問が好きですが、コンパイラの内部やオブジェクト作成の詳細など、他のトピックにまで及ぶ、より複雑な質問を提起します。