public class Base {
<T> List<? extends Number> f1() {return null;}
List<? extends Number> f2() {return null;}
<T extends Number> List<T> f3() {return null; }
}
class Derived extends Base {
List<String> f1() {return null;} // compiles fine !!!
List<String> f3() {return null; } // compiles fine !!!
// compile ERR: return type is incompatible with Base.f2()
List<String> f2() {return null;}
}
Tại sao định nghĩa của phương pháp f1 trọng() và f3() trong lớp Derived cho không có lỗi biên dịch, giống như định nghĩa của trọng phương pháp f2() trong lớp Derived (mang đến cho biên dịch lỗi "kiểu trả về không tương thích với cơ sở. f2() ")?Tại sao các quy tắc đăng ký và bỏ chọn hoạt động theo cách này trên các kiểu trả về khi ghi đè một phương thức chung với một phương thức không chung chung?
Quy tắc ghi đè đăng ký trong JLS cho phép phương thức ghi đè (trong lớp bắt nguồn) không chung chung, trong khi phương thức ghi đè (trong lớp cơ sở) là chung chung.
Quy tắc ghi đè không được chọn cho phép tạo loại trả về trong phân lớp List<String>
thay vì List<T>
trong lớp Cơ sở. Tôi không thể giải thích sự khác biệt về hành vi bên dưới và tôi không hiểu tại sao các định nghĩa trọng số f1() và f3() trong việc biên dịch lớp gốc thành công (trên Eclipse, SE8), bỏ qua các hạn chế do tham số kiểu bị chặn cho f3() và ký tự đại diện bị ràng buộc cho f1()!
P.S. Đoán của tôi - trong f1() và f3() trong trình biên dịch có nguồn gốc xử lý cả hai phương thức như trả về chỉ "thô" List - compiler làm cho xóa (tại thời điểm này chỉ trong Derived !?) đầu tiên, và sau đó so sánh các phương pháp đã xóa trong Derived với unerased (cho đến nay) các phương thức trong Base. Bây giờ quy tắc ghi đè không được kiểm tra là OK (và không cần kiểm tra giới hạn -it chỉ đơn giản là không thể), trình biên dịch quyết định rằng việc ghi đè và biên dịch chính xác đi xa hơn ... và ở đâu đó ở cuối trình biên dịch trong Base.f1() và Base .f3() cũng bị xóa :)))
This SO answer cũng thêm ý tưởng cho chủ đề này.