2009-03-24 33 views
5

Tôi đã đoạn mã sau:Không thể làm tài liệu tham khảo tĩnh để lớp con generic (Java)

class SuperClass { 
    public static String getName() { return "super"; } 
} 

class SubClass extends SuperClass { 
    public static String getName() { return "sub"; } 
} 

public class Dummy<T extends SuperClass> { 
    public void print() { 
     System.out.println("SuperClass: " + SuperClass.getName()); 
     System.out.println("SubClass: " + SubClass.getName()); 
     System.out.println("T: " + T.getName()); 
    } 
    public static void main(String[] args) { 
     new Dummy<SubClass>().print(); 
    } 
} 

Mã này kết quả đầu ra như sau:

SuperClass: super 
SubClass: sub 
T: super 

Câu hỏi của tôi là: Tại sao không làm T .getName() trả về giá trị của SubClass.getName()? Sau khi tất cả, tôi xác định rằng T == SubClass. Hoặc là các cuộc gọi hàm tĩnh không hợp lệ đối với các tham chiếu chung?

Cảm ơn rất nhiều trước!

Trả lời

13

Đây không chỉ là vấn đề về generics.

Nếu bạn nói:

SuperClass obj = new SubClass(); 
System.out.println(obj.getName()); 

bạn cũng sẽ nhận được "siêu". Không có phương pháp tĩnh "đa hình".

Trong trường hợp của bạn, tất cả trình biên dịch biết về T là nó mở rộng SuperClass, do đó, nó sẽ gọi SuperClass.getName().

+0

Ok, điều đó rõ ràng cho đến nay. Nhưng làm thế nào tôi có thể sau đó gọi phương thức tĩnh SubClass.getName() từ Dummy sử dụng T? Tôi muốn có nhiều lớp con hơn nữa với Dummy có thể gọi getName() một cách minh bạch. – JeffreyHammansson

0

Khi bạn instanciated lớp với "new Dummy()" bạn gọi là constructor mặc định mà không thực sự thiết lập bất cứ điều gì. Khi phương thức in được gọi, VM thấy rằng kiểu T, như được khai báo trong khai báo lớp, là SuperClass; Sau đó nó gọi phương thức tĩnh trên lớp này.

1

Không giống như C mẫu ++, Java Generics làm việc theo loại tẩy xoá, vì vậy nó chỉ tạo ra một lớp cho tất cả các giá trị của T, và chuyển tất cả các tài liệu tham khảo để gõ T trong lớp này để loại siêu T, trong trường hợp này SuperClass, sau đó sử dụng công văn ảo để cung cấp phương sai cho các cuộc gọi đến các phương thức đối tượng và gửi công văn tĩnh đến các cuộc gọi đến các phương thức tĩnh.

Vì vậy, khi bạn thực hiện Dummy<SubClass>.print(), trình biên dịch sẽ không thay thế toàn cầu là T bằng SubClass trong Dummy. Tất cả trình biên dịch thực hiện kiểm tra việc sử dụng số T làm đối số hoặc kiểu trả về theo phương thức DummySubClass. Không có thay đổi đối với bất kỳ mã nào bên trong Dummy, vì vậy cùng một phương thức tĩnh SuperClass được gọi là bất cứ điều gì T là.

Nếu bạn muốn hành vi khác nhau trong một lớp chung loại tùy thuộc vào loại tham số, bạn đã vượt qua một đối tượng thuộc loại đó và sử dụng phương pháp ảo hoặc chuyển vào lớp cho loại và sử dụng phản chiếu.

Các vấn đề liên quan