スーパータイプへの参照の型を持つ変数は、サブタイプのインスタンスへの参照を保持できます。サブタイプのインスタンスを変数に割り当てても、インスタンスはまったく変更されません。参照の種類を広げるだけです。すべてのインスタンス データはまだそこにあり、ダウンキャストによって取得できます。あれは、
Student s = new Student("John", "Master's");
Person p = s; // no cast needed for a widening conversion
は次とまったく同じです:
Person p = new Student("John", "Master's");
Student s = (Student) p; // cast required for a narrowing conversion
編集おそらくこれは物事を明確にするのに役立ちます。の 2 番目のサブクラスがあるとしPerson
ます。
class Teacher extends Person
{
private String department;
}
今、あなたはこれを行うことができます:
Person p = new Teacher("Fred", "Physics");
Teacher t = (Teacher) p;
ただし、後でこれを実行しようとした場合:
p = new Teacher("Fred", "Physics");
Student s = (Student) p; // Error!
ClassCastException
プログラムのその時点で、はではないp
オブジェクト ( のインスタンス) への参照になっているため、 が得られます。Teacher
Student
ここに類推があります。英語では、「I have a pet animal」と言うかもしれません。これは動物の種類については何も言いません。(たとえば、ペットが吠えるかどうかはわかりません。) 一方、「私はペットの犬を飼っています」と言う場合、見知らぬ人に吠えるかどうかを尋ねるのは理にかなっています。重要な点は、あなたのペットを動物と呼んでも、それが犬である (またはそうでない) という事実は変わらないということです。Java 参照でもまったく同じことが起こっています。より一般的な (基本クラスなどの) 参照型を使用してオブジェクト参照を格納しても、オブジェクト自体の性質は変わりません。オブジェクトの詳細についての知識は失われますが、それらの詳細はまだそこにあります。
コメントで述べた点を繰り返します。Java ではオブジェクトを変数に割り当てることはありません。オブジェクトへの参照のみを割り当てます。別の言い方をすれば、どの変数もオブジェクトではありません。