Triest
Java-программы не имеют прямого доступа к памяти, поэтому вы не должны беспокоиться о вопросах памяти. Реализация памяти может быть специфичной для реализации виртуальной машины Java. Однако я могу обрисовать вам общий процесс.
Для того чтобы этот код работал, класс Sample1 должен быть потомком класса Sample. Каждый класс представлен в памяти данными (переменными-членами класса) и таблицей vtable. Vtable-это массив указателей на виртуальные методы, принадлежащие этому классу. Например, если класс Sample определен следующим образом:
public class Sample {
int var1;
int var2;
Sample() {}
public void method1() {}
public void method2() {}
}
он может быть представлен в памяти следующим образом:
vtable pointer<br />
var1<br />
var2
где указатель vtable указывает на этот массив указателей на методы:
<br />
0: method1 from Sample class<br />
1: method2 from Sample class
Если у вас есть класс-потомок Sample1, подобный этому:
public class Sample1 extends Sample {
int var3;
Sample1() {}
@Override
public void method1() {}
@Override
public void method2() {}
}
он будет представлен в памяти следующим образом:
vtable pointer<br />
var1<br />
var2<br />
var3
где указатель vtable указывает на этот массив указателей на методы:]
0: method1 from Sample1 class<br />
1: method2 from Sample1 class
Когда вы создадите экземпляр класса Sample1 с помощью new, он создаст вышеуказанную структуру памяти для класса Sample1. Когда вы назначаете его переменной типа Sample:
Sample sample = new Sample1();
компилятор позволит это сделать, потому что класс Sample1 может быть использован в качестве класса Sample без проблем. Действительно, экземпляр класса Sample1 имеет те же переменные (var1, var2), что и класс Sample, и находится в тех же позициях. Что касается класса Sample1 vtable, то он имеет методы с той же сигнатурой и в тех же позициях, что и класс Sample. Таким образом, вы можете безопасно работать с классом Sample1 через переменную Sample, поскольку она совместима с ним. Надеюсь, это объяснение вам поможет.