2011-09-05 24 views
9

Tôi có siêu lớp như:Tại sao tôi nhận được các phương thức lớp cơ sở thông qua sự phản chiếu khi lớp con ghi đè chúng?

class MyClass<T> { 
    public void setValue(T value){ 
    //insert code 
    } 

    public T getValue(){ 
    return null; 
    } 
} 

sau đó tôi có aa nguồn gốc cụ thể

class MyClassImp extends MyClass<String> { 
    @Override 
    public void setValue(String value){ 
    //insert code 
    } 

    @Override 
    public String getValue(){ 
    return null; 
    } 
} 

On phản ánh trên MyClassImpl như:

Class clazz = MyClassImpl.class; 
Method[] methods = clazz.getDeclaredMethods(); 

tôi nhận được cả hai thực hiện lớp cha java.lang.Object getValue(), void setValue(java.lang.Object)java.lang.String getValue(), void setValue(java.lang.String).

Theo tài liệu Java của Class.getDeclaredMethods() vis-a-viz

Trả về một mảng các đối tượng Phương pháp phản ánh tất cả các phương pháp tuyên bố bởi lớp hoặc giao diện được đại diện bởi đối tượng Class này. Điều này bao gồm truy cập công cộng, được bảo vệ, mặc định (gói) và các phương thức riêng tư, nhưng không bao gồm các phương thức kế thừa. Các phần tử trong mảng được trả về không được sắp xếp và không theo bất kỳ thứ tự cụ thể nào. Phương thức này trả về một mảng có độ dài 0 nếu lớp hoặc giao diện khai báo không có phương thức nào, hoặc nếu đối tượng Class này đại diện cho một kiểu nguyên thủy, một lớp mảng hoặc là void. Phương thức khởi tạo lớp <clinit> không được bao gồm trong mảng được trả về. Nếu lớp khai báo nhiều phương thức thành viên công khai có cùng các kiểu tham số, chúng đều được bao gồm trong mảng được trả về.

Tại sao tôi nhận được triển khai loại siêu? Có điều gì tôi thiếu không?

Lý do tại sao tôi cần điều này là tôi gọi một cách phản ánh setValue về triển khai lớp cơ sở, mà tôi đã thêm một số chú thích chú thích đặc biệt và tất nhiên các ràng buộc bổ sung.

+1

Có thể là bản sao của lưu lượng truy cập http: // stackoverflow.com/questions/5756081/java-generics-reflection –

+1

@RC: Tôi không thấy nó có thể trùng lặp với câu hỏi đó như thế nào. –

+0

@RC đây không phải là một bản sao chính xác – amod

Trả lời

13

Đó là do lớp được biên dịch thực sự là không khai báo setValue(Object). Phương thức đó sẽ chuyển sang String, và sau đó gọi phương thức được gõ mạnh. Tương tự như vậy getValue(Object) gọi getValue(String). Về cơ bản, điều này là bắt buộc vì JVM không thực sự biết về generics (ít nhất là không theo một chiều sâu) - để ghi đè lên phương thức superclass ở cấp JVM, nó phải có cùng một chữ ký.

Có một cái nhìn tại các lớp học với javap -c MyclassImp bạn sẽ thấy các phương pháp tổng hợp thêm:

public java.lang.Object getValue(); 
    Code: 
    0: aload_0 
    1: invokevirtual #3; //Method getValue:()Ljava/lang/String; 
    4: areturn 

public void setValue(java.lang.Object); 
    Code: 
    0: aload_0 
    1: aload_1 
    2: checkcast  #4; //class java/lang/String 
    5: invokevirtual #5; //Method setValue:(Ljava/lang/String;)V 
    8: return 

} 
+4

Lưu ý rằng 'Method.isSynthetic()' sẽ trả về 'true' cho những phương thức được tạo ra có/trả về' Object'. Đó là một cách hay để phân biệt các phương thức đó với các phương thức "thực". –

+0

Hành vi trình biên dịch này có được ghi lại ở đâu đó không? –

+0

@ Ryan: Tôi không biết, tôi sợ. Nhìn lướt qua JLS, tôi không thể nhìn thấy nó - mặc dù tình huống này được đề cập ở một vài nơi. –

1

Như Jon đã nói trước đó, loại thông tin bị mất trong thời gian chạy cho generics.

Vì vậy, bất cứ khi nào bạn sử dụng generics, trình biên dịch sẽ đặt tất cả các phương thức "chung" kế thừa đó vào lớp con. Điều này cũng không đúng với mã không chung chung.

Tôi vừa kiểm tra: khi tôi xóa mã liên quan chung (phần <T>) khỏi lớp cha và mã phản chiếu đã cho tôi chính xác hai phương thức trong lớp con mặc dù nó ghi đè chúng. Nó ngụ ý rằng tài liệu nên có một chút rõ ràng cho mã liên quan đến chung chung.

+0

Nói đúng những phương pháp đó không có ở đó vì các generics (như bạn đã nhận thấy). Chúng có đó bởi vì các phương thức sử dụng phương sai hiệp phương thức trả về (tức là lớp con trả về một giá trị cụ thể hơn loại cơ sở). Đó là * thường xuyên nhất * được sử dụng kết hợp với generics, nhưng có thể được sử dụng độc lập. –

+0

Có! Tôi vừa xác minh. – Santosh

+0

vâng tôi đã xác minh tất cả các tình huống, trong đó tôi ghi đè ở dạng chung chung và hình thức rõ ràng. với dạng chung, tôi chỉ có hai phương pháp, với hiệp phương sai, tôi nhận thấy hai phương pháp bổ sung và chúng được đánh dấu là tổng hợp – maress

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