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?


108

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 triển khai 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 các phương thức phù hợp. Thậm chí nếu các loại chú thích được chú thích với Kế thừa 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 doc java:

Cũng lưu ý rằng meta-annotation này chỉ khiến các chú thích được kế thừa từ các lớp cha; chú thích trên các 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 một đối tượng thực hiện trong thời gian chạy không phải là điều quá khó để làm vì vậy phải có lý do chính đáng đằng sau quyết định này.

Câu trả lời:


130

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

Thí 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()

kết quả sẽ là gì? 'baz', 'phleem' hay 'flopp'?


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


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

6
Tôi không biết, mọi người. Trong trường hợp này (nếu lỗi đánh máy không có), tôi sẽ mong đợi The field value is ambiguous.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 không phải là một trường, nhưng các giá trị chú thích được giải quyết tất cả tại thời điểm biên dịch, phải không? Tính năng mà chúng tôi đang thiếu ở đây sẽ cực kỳ hữu ích trong nhiều trường hợp. Nhân tiện xin lỗi về việc khôi phục một bài viết cũ :).
Petr Janeček

7
@Slanec hãy xem cách các nguồn của Spring để xem các bạn Spring đã giải quyết những vấn đề này như thế nào. Xem AnnotationUtils.findAnnotation (phương pháp, annotationType)
Sean Patrick Floyd

1
Tôi đang xem xét viết một cái gì đó tương tự như thế này. Với một số loại bộ nhớ đệm đơn giản, đây có vẻ là một cách phù hợp với tôi. Cảm ơn! Trong ví dụ trên, nó sẽ tìm thấy Foochú thích của '( MyClasskhông có chú thích , sau đó các Giao diện được tìm kiếm và lấy theo thứ tự sau đó implements) và do đó in ra "baz". Mát mẻ.
Petr Janeček

2
@WChargin đúng, nó chỉ mất 2 năm đối với một ai đó để phát hiện rằng typo :-)
Sean Patrick Floyd

35

Từ Javadoc cho @Inhe inherit:

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

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

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

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

Sau đó, các xác nhận hiệu quả trên Student.getAge()@Nonnull @Min(5). @Nonnullkhông có @Inheritedchú thích meta.


4
Đây phải là câu trả lời được chọn
Andrzej Purtak

3
Ví dụ của bạn mâu thuẫn với câu trả lời của bạn, mà nói rằng @Inheritedkhông ảnh hưởng đến bất cứ điều gì khác hơn là lớp
Oleg MIKHEEV

@Chỉ kế thừa hoạt động khi bạn sử dụng chú thích trên Lớp
Carlos Parker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.