В то время как основной принцип полиморфизма заключается в развязывании «что из кого» в терминах types
, но что меня смущает, как выясняется механизм вызова метода и вызывает правильное тело метода в полиморфизме.Как Java Определяет методы вызова во время выполнения в полиморфизме?
Поскольку в Java все метод связывания является late-binding
, если метод не является static
, final
или private
и позднего связывания выполняется JVM, который предварительно вычисляет method table
для каждого класса, а затем сделать таблицу просмотра во время выполнения в обычном вызове метода.
Но то же самое происходит и при полиморфизме. Например
Предположим, что У меня есть универсальный класс Cycle
с ride()
методом
class Cycle {
public void ride(){
System.out.println("I'm Riding generic Cycle()");
}
}
И у меня есть три специализированного класса Bicycle
Tricycle
и Unicycle
, который расширяет универсальный класс Cycle
и переопределяет его метод ride()
.
class Bicycle extends Cycle {
public void ride() {
System.out.println("I'm riding Bicycle");
}
}
class Tricycle extends Cycle{
public void ride() {
System.out.println("I'm riding Tricycle ");
}
}
class Unicycle extends Cycle {
public void ride() {
System.out.println("I'm Riding Unicycle ");
}
}
Это TestRide
класс Протестируйте выше полиморфизм.
public class TestRide {
public static void ride(Cycle c){
c.ride();
}
public static void main(String[] args){
Cycle Cycling = new Cycle();
ride(Cycling);
Bicycle bi = new Bicycle();
ride(bi);
Tricycle tri = new Tricycle();
ride(tri);
Unicycle uni = new Unicycle();
ride(uni);
}
}
Выход является
I'm Riding generic Cycle()
I'm riding Bicycle
I'm riding Tricycle
I'm Riding Unicycle
Байт Код:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=5, args_size=1
0: new #17 // class com/polymorphism/Cycle
3: dup
4: invokespecial #24 // Method com/polymorphism/Cycle."
<init>":()V
7: astore_1
8: aload_1
9: invokestatic #25 // Method ride:(Lcom/polymorphism/
Cycle;)V
12: new #27 // class com/polymorphism/Bicycle
15: dup
16: invokespecial #29 // Method com/polymorphism/Bicycle
."<init>":()V
19: astore_2
20: aload_2
21: invokestatic #25 // Method ride:(Lcom/polymorphism/
Cycle;)V
24: new #30 // class com/polymorphism/Tricycle
27: dup
28: invokespecial #32 // Method com/polymorphism/Tricycl
e."<init>":()V
31: astore_3
32: aload_3
33: invokestatic #25 // Method ride:(Lcom/polymorphism/
Cycle;)V
36: new #33 // class com/polymorphism/Unicycle
39: dup
40: invokespecial #35 // Method com/polymorphism/Unicycl
e."<init>":()V
43: astore 4
45: aload 4
47: invokestatic #25 // Method ride:(Lcom/polymorphism/
Cycle;)V
50: return
Даже в байткод его так же, как обычный вызов метода с invokestatic
и invokespecial
в то время как я думал, что он будет использовать invokedynamic
на рисунке выведите версию метода, подходящую для фактического типа объекта. Но это было не так.
Так как же Java выяснить фактический вызов метода во время полиморфизма пока мы просто передать upcasted объект в ride()
метод как ride(bi)
в TestRide
классе?
EDIT: RIDE метод ByteCode
public static void ride(com.polymorphism.Cycle);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokevirtual #16 // Method com/polymorphism/Cycle.r
ide:()V
4: return
Возможно, ваш тестовый пример слишком прост. Если компилятор Java знает во время компиляции, какой метод будет вызываться, нет необходимости в байт-коде, который делает что-то динамически. – mastov
'invokedynamic' был введен в байт-код JVM для динамического поиска методов, который * не * следит за поиском метода Java. Почему компилятор Java использует его? Отправка виртуального метода выполняется с помощью 'invokevirtual' и' invokeinterface'. Обратите внимание, что Java-компилятор, конечно, может свободно использовать 'invokedynamic', если захочет. Спецификация языка Java ничего не говорит о том, как должна быть скомпилирована Java, она даже не говорит, что ее нужно скомпилировать вообще, ее можно так же интерпретировать. –
@ JörgWMittag Получил вашу точку :). Но вопрос о том, как он это делает, остается –