x2コンパイル時の型は ですXが、実行時の型はYです。これが意味することは、コンパイラがx2それについて推論する必要があるとき、それx2がX. しかし、実行時には、 の動作は の動作にx2なりますY。
では、これをもう少し冗長に説明しましょう。これは合法ではありません:
x2.do2();
これは、コンパイラがそれをx2であるXと見なしX、 という名前のメソッドを持たずdo2、 しかY持たないためです。コンパイラは が であることを認識せず、 のコンパイル時の型が であるx2ことYのみを認識します。x2X
ただし、これは正当であり、実行時例外は発生しません。
((Y)x2).do2();
私たちはコンパイラに、ほら、私はあなたよりも について知っていると言っていますx2。であることはわかっているので、 を受信側としてY呼び出す命令を発行するだけY.do2です。x2
さらに、 s を受け入れるメソッドがあると仮定しましょうY:
void M(Y y) { }
次に、これは合法ではありません。
M(x2);
繰り返しますが、これは、すべての s がs でx2あるとは限らず、コンパイラーがそれを と見なすためです。そのため、メソッドの呼び出しを拒否する必要があります。XXY
ただし、これは正当であり、実行時例外は発生しません。
M((Y)x2);
繰り返しますが、私たちはコンパイラに、あなたが知っているよりも多くのことを知っていると伝えていますx2。私はそれが であることを知っているYので、私を信じて、あたかもx2であるかのようにそのメソッドを呼び出してくださいY。
Xさらに、 で定義され、 でオーバーライドされたメソッドがあると仮定しましょうY:
class X {
void do1() {}
void N() { System.out.println("X");
}
class Y extends X { void do2() {}
@Override
void N() { System.out.println("Y");
}
ここで、次のように言います。
x2.N();
Yコンソールに表示されます。これは、 のランタイムタイプが であるためx2ですY。
これらはすべて、人々がポリモーフィズムについて話すときの意味の一部です。
2 つのコンストラクターを使用してオブジェクトを作成することは合法ですか?
このステートメントには 2 つのコンストラクターはありません。
X x2 = new Y();
コンストラクターは 1 つだけです。左辺は変数宣言です。x2typeという名前の変数を宣言していますX。右側はコンストラクターの呼び出しです。Y;のパラメーターなしのパブリック コンストラクターを呼び出しています。これにより、 の新しいインスタンスが作成されますY。ステートメント全体が代入ステートメントです。右側の結果を左側の変数に代入しています。Yすべての s はポリモーフィックにもXs であるため、代入は正当ですY extends X。