2011-01-20 19 views
91

Używam AOP Guice do przechwytywania niektórych wywołań metod. Moja klasa implementuje interfejs i chciałbym opisać metody interfejsu, aby Guice mógł wybrać właściwe metody. Nawet jeśli typ adnotacji jest opatrzone Inherited adnotacja realizacji klasę nie dziedziczy adnotację, jak określono w Inherited Java Doc:Dlaczego klasy java nie dziedziczą adnotacji z zaimplementowanych interfejsów?

Należy również zauważyć, że w tym meta-adnotacja powoduje jedynie adnotacje być dziedziczone z nadrzędnych; adnotacje na zaimplementowanych interfejsach nie działają.

Jaki może być tego powód? Zapoznanie się z wszystkimi interfejsami, które klasa obiektu implementuje w środowisku wykonawczym, nie jest trudną rzeczą, więc decyzja musi być uzasadniona.

Odpowiedz

109

Powiedziałbym, że powodem jest to, że w przeciwnym razie wystąpiłby problem związany z wielokrotnym dziedziczeniem.

Przykład:

@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{} 

Gdybym to zrobić:

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

co wynik będzie? "baz", "phleem" lub "flopp"?


Z tego powodu adnotacje na interfejsach rzadko są przydatne.

+8

adnotacje na interfejsach są przydatne tylko wtedy, gdy posiadasz framework, który je obsługuje.BTW w tym przykładzie getAnnotation() zwraca null;) –

+5

Nie wiem, ludzie. W tym przypadku (gdyby nie było literówki), spodziewałbym się, że wartość pola jest niejednoznaczna. Podobnie jak w przypadku dwóch interfejsów deklarujących tę samą stałą o różnych wartościach. Wiem, że to nie jest pole, ale wartości adnotacji są rozwiązywane podczas kompilacji, prawda? Funkcja, której tu brakuje, byłaby bardzo pomocna w wielu przypadkach. Przepraszam, że przywracam stary post, nawiasem mówiąc :). –

+6

@Slanec przyjrzyj się źródłom Springa, aby przekonać się, jak ludzie z zespołu Spring pracowali nad tymi problemami. Zobacz [AnnotationUtils.findAnnotation (method, annotationType)] (http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-core/3.1.1.RELEASE/org/springframework/core/ adnotacja/AnnotationUtils.java # AnnotationUtils.findAnnotation% 28java.lang.reflect.Method% 2Cjava.lang.Class% 29) –

29

Z Javadoc dla @Inherited:

Wskazuje, że typ adnotacji jest automatycznie dziedziczona. Jeśli meta-adnotacja o wartości jest dziedziczona w deklaracji typu adnotacji , a użytkownik zapytuje o typ adnotacji na deklaracji klasy , a deklaracja klasy nie ma adnotacji dla tego typu , wtedy nadklasa klasy będzie automatycznie sprawdzana pod kątem Typ adnotacji. Ten proces zostanie powtórzony, dopóki nie zostanie znaleziony adnotacja lub górna część hierarchii klas (Obiekt) osiągnie wartość . Jeśli żadna nadklasa nie ma adnotacji dla tego typu, zapytanie wskazuje, że dana klasa nie ma takiej adnotacji. Należy pamiętać, że ten typ meta-adnotacji nie przynosi efektu, jeśli przypisany komentarz typu jest używany do opisywania niczego poza klasą. Zauważ także, że ta meta-adnotacja powoduje, że adnotacje są dziedziczone po nadklasach od ; adnotacje na zaimplementowanych interfejsach nie mają wpływu.

Z drugiej strony weryfikatory JSR 305 wykonują pewien rodzaj sprawdzania dziedziczenia. Jeśli masz hierarchię klas:

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

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

Wtedy skuteczne walidacje na Student.getAge()@Nonnull @Min(5). @Nonnull nie ma meta-adnotacji @Inherited.

+4

Ten powinien być wybraną odpowiedzią – Ondreju

+2

Twój przykład jest sprzeczny z twoją odpowiedzią, która mówi, że '@ Dziedziczony' nie ma wpływu na nic poza klasą –

Powiązane problemy