Trong khi nguyên tắc chính của đa hình là tách "những gì từ ai" trong điều khoản của types
, nhưng những gì gây nhầm lẫn cho tôi như thế nào cơ chế gọi phương thức phát hiện và gọi cơ thể phương pháp chính xác trong đa hình.Làm thế nào để Java Xác định các phương thức gọi lúc chạy trong đa hình?
Vì trong java tất cả các phương pháp ràng buộc là late-binding
trừ khi phương pháp này là static
, final
hoặc private
, và late-binding được thực hiện bởi JVM mà precomputes method table
cho mỗi lớp và sau đó làm một bảng tra cứu trong thời gian chạy trong cuộc gọi phương pháp thông thường.
Nhưng điều tương tự cũng xảy ra trong quá trình đa hình. Ví dụ
Giả sử tôi đã một lớp Generic Cycle
với một phương pháp ride()
class Cycle {
public void ride(){
System.out.println("I'm Riding generic Cycle()");
}
}
Và tôi có ba chuyên ngành Lớp Bicycle
Tricycle
và Unicycle
kéo dài Generic lớp Cycle
và ghi đè phương pháp ride()
của nó.
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 ");
}
}
Đây là lớp TestRide
để kiểm tra tính đa hình trên.
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);
}
}
Các Output là
I'm Riding generic Cycle()
I'm riding Bicycle
I'm riding Tricycle
I'm Riding Unicycle
Byte Code:
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
Ngay cả trong bytecode của nó cũng giống như lời gọi phương thức thông thường với invokestatic
và invokespecial
trong khi tôi nghĩ rằng nó sẽ sử dụng invokedynamic
với con số ra phiên bản của phương thức phù hợp với loại đối tượng thực tế. Nhưng đó không phải là trường hợp.
Vậy Java làm cách nào để tìm ra phương thức thực tế trong suốt quá trình đa hình trong khi chúng ta chỉ truyền một đối tượng upcasted trong phương thức ride()
như ride(bi)
trong lớp TestRide
?
EDIT: RIDE phương pháp 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
Có thể trường hợp thử nghiệm của bạn quá đơn giản. Nếu trình biên dịch Java biết tại thời gian biên dịch, phương thức nào sẽ được gọi, không cần bytecode làm bất cứ điều gì động. – mastov
'invokedynamic' được giới thiệu trong JVM bytecode để tra cứu phương thức động * không * theo tra cứu phương thức của Java. Tại sao một trình biên dịch Java sử dụng nó? Phương thức xử lý ảo được thực hiện với 'invokevirtual' và' invokeinterface'. Lưu ý rằng một trình biên dịch Java là tất nhiên miễn phí để sử dụng 'invokedynamic' nếu nó muốn. Đặc tả Ngôn ngữ Java không nói gì về cách Java được biên dịch, nó thậm chí không nói nó phải được biên dịch chút nào, nó cũng có thể được giải thích. –
@ JörgWMittag Có điểm của bạn :). Nhưng câu hỏi về việc nó vẫn như thế nào vẫn còn –