Điều này có nghĩa là nếu bạn có một phương thức có kiểu trả về biến đổi (hẹp hơn), trình biên dịch sẽ tạo ra phương thức tổng hợp cầu tổng hợp cho bạn và gọi phương thức ghi đè thông qua phương thức cầu này. Hiệp phương sai trong kiểu trả về đã được giới thiệu trong Java 5, cùng lúc với Generics và nó được thực hiện bằng cách sử dụng phương thức cầu cầu.
Ví dụ 1: Phương sai hiệp phương theo kiểu trả về cũng được thực hiện bằng phương pháp cầu tổng hợp ngay cả khi không có generics.
Ví dụ:
abstract class A {
public abstract A get();
}
class B extends A {
@Override
public B get() {
return this;
}
}
sẽ được thực hiện trong bytecode bởi trình biên dịch sử dụng một phương pháp tổng hợp cầu mà đại biểu cho phương thức ban đầu. Về nguyên tắc, bạn có thể tưởng tượng rằng các trình biên dịch ghi đè hiệp biến như sau:
abstract class A {
public abstract A get();
}
class B extends A {
//bytecode only bridge method
@Override
public A get() {
return get;
}
public B get() {
return this;
}
}
Ví dụ 2 - Generics: Hãy xem xét một ví dụ khi Generics có liên quan.
abstract class A<T> {
public abstract T get();
}
class B extends A<String> {
@Override
public String get() {
return "hello";
}
}
Phương pháp này get()
của lớp B
là hiệp biến trong kiểu trả về với phương pháp get
trong lớp A
. Khi biên dịch bit mã này trình biên dịch sẽ thực hiện xóa có nghĩa là nó sẽ thay thế generics với giới hạn của họ và thêm phôi để đảm bảo rằng tất cả mọi thứ hoạt động.
Sau khi tẩy xoá các lớp trông như thế này:
abstract class A {
public abstract Object get();
}
class B extends A {
@Override
public String get() {
return "hello";
}
}
Bây giờ kể từ khi phương pháp chữ ký của get
là public Object get()
mà không phải là một chữ ký đó là hiện diện trong lớp B
trình biên dịch sẽ tạo ra một phương pháp cầu trong lớp B
trong để đạt được trọng số.
Bạn có thể nghĩ về lớp học B
giống như bên dưới. Tuy nhiên, điều quan trọng cần lưu ý là mã bên dưới sẽ không bao giờ được tạo. Nó sẽ không biên dịch. Trình biên dịch chỉ tạo phương thức tương đương get
trong bytecode.
class B extends A {
//bridge method
@Override
public Object get() {
return get();
}
public String get() {
return "hello";
}
}
Mỗi sử dụng đa hình của lớp B
qua A
mà gọi get
sẽ gọi phương thức cầu đó sẽ uỷ thác cho get thực phương pháp.
Rất thú vị! Và không có lỗi vì hai phương thức có cùng tên/tham số trong cùng một lớp? I E. thông báo "Phương thức trùng lặp getType() trong loại Vòng kết nối"? – sp00m
@ sp00m: sẽ xảy ra lỗi nếu bạn cố chuyển nó tới trình biên dịch Java, vì các phương thức không thể khác nhau chỉ bằng kiểu trả về. Nhưng ở cấp độ bytecode JVM, hạn chế đó không tồn tại. – mhsmith