2011-01-20 8 views
91

Tôi đã sử dụng AOP của Guice để chặn một số cuộc gọi phương thức. Lớp của tôi thực hiện một giao diện và tôi muốn chú thích các phương thức giao diện để Guice có thể chọn đúng phương thức. Thậm chí nếu các loại chú thích được chú thích với Inherited chú thích thực hiện lớp không kế thừa các chú thích như đã nêu trong Kế thừa của java doc:Tại sao các lớp java không kế thừa các chú thích từ các giao diện được triển khai?

Cũng lưu ý rằng đây meta-chú thích chỉ gây chú thích là thừa hưởng từ superclasses; chú thích trên giao diện được triển khai không có hiệu lực.

Điều gì có thể là lý do cho điều này? Tìm hiểu tất cả các giao diện mà lớp của đối tượng thực hiện trong thời gian chạy không phải là việc khó để làm như vậy phải có lý do chính đáng đằng sau quyết định này.

Trả lời

109

Tôi muốn nói lý do là nếu không, một vấn đề đa thừa kế sẽ xảy ra.

Ví dụ:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) @Inherited 
public @interface Baz { String value(); } 

public interface Foo{ 
    @Baz("baz") void doStuff(); 
} 

public interface Bar{ 
    @Baz("phleem") void doStuff(); 
} 

public class Flipp{ 
    @Baz("flopp") public void doStuff(){} 
} 

public class MyClass extends Flipp implements Foo, Bar{} 

Nếu tôi làm điều này:

MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value() 

những gì kết quả sẽ là? 'baz', 'phleem' hoặc 'flopp'?


Vì lý do này, chú thích trên giao diện hiếm khi hữu ích.

+8

chú thích trên giao diện chỉ hữu ích nếu bạn có một khung công tác hỗ trợ chúng.BTW trong ví dụ này getAnnotation() trả về null;) –

+5

Tôi không biết, mọi người. Trong trường hợp này (nếu không có lỗi đánh máy), tôi mong đợi một 'Giá trị trường là mơ hồ.' giống như lỗi trình biên dịch giống như với hai giao diện khai báo cùng một hằng số với các giá trị khác nhau. Tôi biết rằng đây là _not_ một trường, nhưng các giá trị chú thích nhận được tất cả được giải quyết tại thời gian biên dịch, phải không? Tính năng chúng tôi thiếu ở đây sẽ cực kỳ hữu ích trong nhiều trường hợp. Xin lỗi về việc khôi phục một bài đăng cũ, nhân tiện :). –

+6

@Slanec có một cái nhìn tại cách các nguồn Spring để xem cách các chàng trai mùa xuân làm việc xung quanh những vấn đề này. Xem [AnnotationUtils.findAnnotation (method, annotationType)] (http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-core/3.1.1.RELEASE/org/springframework/core/ Chú thích/AnnotationUtils.java # AnnotationUtils.findAnnotation% 28java.lang.reflect.Method% 2Cjava.lang.Class% 29) –

29

Từ Javadoc cho @Inherited:

Chỉ ra rằng một loại chú thích được tự động di truyền. Nếu Chú thích meta thừa kế có trên một loại chú thích tuyên bố và người dùng truy vấn loại chú thích trên khai báo lớp học và tuyên bố lớp không có chú thích cho loại này, thì lớp cha của lớp sẽ tự động được truy vấn loại chú thích. Quá trình này sẽ được lặp lại cho đến khi chú thích cho loại này được tìm thấy hoặc phần đầu của phân cấp lớp (Object) là . Nếu không có siêu lớp nào có chú thích cho loại này, thì truy vấn sẽ cho biết rằng lớp được đề cập không có chú thích như vậy. Lưu ý rằng loại chú giải meta này không có hiệu lực nếu loại được chú thích được sử dụng để chú thích bất kỳ thứ gì ngoài một lớp. Cũng lưu ý rằng siêu chú thích này chỉ khiến chú thích được kế thừa từ các siêu lớp; chú thích trên các giao diện được triển khai không có hiệu lực.

Mặt khác, trình xác thực JSR 305 thực hiện một số kiểu tra cứu thừa kế. Nếu bạn có một hệ thống các lớp:

//Person.java 
@Nonnull 
public Integer getAge() {...} 

//Student.java (inherits from Person) 
@Min(5) 
public Integer getAge() {...} 

Sau đó kiểm chứng thực hiệu quả trên Student.getAge()@Nonnull @Min(5). @Nonnull không có chú thích meta @Inherited.

+4

Câu hỏi này phải là câu trả lời được chọn – Ondreju

+2

ví dụ của bạn mâu thuẫn với câu trả lời của bạn, nói rằng '@ Kế thừa' không ảnh hưởng đến bất kỳ thứ gì ngoài lớp –