2011-10-14 46 views
11

Hãy có hệ thống phân cấp lớp sau đây:Lỗi Generics Java?

public class MyType { 
} 

public class MySuperclass<T extends MyType> { 
    protected Map<String, String> myMap = new TreeMap<String, String>(); 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

public class MySubclass extends MySuperclass { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); // <-- compilation error 
    } 
} 

Tại sao có một lỗi biên dịch trong phương pháp overriden của MySubclass? Thông báo lỗi là "Loại không phù hợp: không thể chuyển đổi từ đối tượng thành chuỗi".

Điều thú vị là các dissapears lỗi biên dịch nếu tôi xác định Generics loại lớp cho MySuperclass trong MySubclass định nghĩa:

public class MySubclass extends MySuperclass<MyType> { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

ai đó có thể giải thích hành vi này? Tôi sẽ coi nó là một lỗi trình biên dịch Java.

Tôi đang sử dụng jdk1.6.0_24.

Trả lời

12

Nó không phải là lỗi. Bằng cách mở rộng MySuperclass thay vì MySuperclass<MyType>, bạn đang mở rộng loại thôMySuperclass, có nghĩa là myMap cũng sẽ thuộc loại Map thay vì Map<String, String>.

+1

chính xác. Đó là một trong những "puzzlers" của Bloch. – Bozho

+0

Vì vậy Generics là tất cả hoặc không có gì? Nếu bạn sử dụng một loại thô, bạn sẽ không nhận được bất kỳ generics cho loại đó, thậm chí không phải là các phần mà không phụ thuộc vào 'T' ở tất cả? – Thilo

+2

Nhưng những gì có định nghĩa chung của 'MySuperclass ** **' chung với Generics của 'Map ** ** myMap'? Đó là hai định nghĩa generics khác nhau không có 'kết nối' giữa chúng. Tôi không hiểu. –

0

nếu Foo là một subtype (phân lớp hoặc subinterface) của Bar, và G là một số khai báo kiểu generic , nó không phải là trường hợp đó G là một subtype của G.

Bạn có thể tham khảo http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf (đối với biết thêm thông tin)

1

Thực sự không hợp lý. Điều này có thể được coi là một lỗi trong thiết kế. Nguyên nhân gốc rễ là quyết định giữ API tổng hợp tương thích ngược, thay vì giữ nguyên nguyên tắc cũ và giới thiệu API tổng quát mới. Quyết định này về mặt kỹ thuật là vô nghĩa, và những lời giải thích của họ là buồn cười. Lý do thực sự đằng sau nó có lẽ là Sun đã buộc phải đẩy ra Java5 nhưng không có đủ nguồn lực, vì vậy họ đã lấy con đường dễ dàng (xóa). Vì vậy, ở đây chúng tôi, hoàn toàn hơi say. Hệ thống loại bastard này không chỉ là một vấn đề trong chính nó, nó cũng là một trở ngại lớn cho việc giới thiệu bất kỳ tính năng mới nào.