2017-07-28 94 views
4

所以,我的問題是以下,我使用註釋來標記類的方法。方法註解繼承

我的主要註釋是@Action,我需要對@SpecificAction的特定方法有更強的註釋。

所有用@SpecificAction註解的方法必須註釋爲@Action。 我的想法是有@SpecificAction註釋@Action

@Action 
[other irrelevant annotations] 
public @interface SpecificAction{} 

@SpecificAction 
public void specificMethod(){} 

我希望specificMethod.isAnnotationPresent(Action.class)是真實的,但事實並非如此。

我怎樣才能使@Action註釋是「繼承」?

+0

'@Action @SpecificAction公共無效specificMethod(){}' – Michael

+0

相關:https://stackoverflow.com/questions/1624084/why-is-not-possible-to-extend-annotations-in-java – assylias

+0

你可以通過添加一個屬性來解決這個問題,比如'String type()默認的「base」;'或'boolean isSpecific default false;'到你的註解中。 –

回答

3

正如@ assylias的鏈接稱,批註不能被繼承,但是你可以使用的成分,和遞歸搜索目標的註釋是這樣的:

public static class AnnotationUtil { 

    private static <T extends Annotation> boolean containsAnnotation(Class<? extends Annotation> annotation, Class<T> annotationTypeTarget, Set<Class<? extends Annotation>> revised) { 
     boolean result = !revised.contains(annotation); 
     if (result && annotationTypeTarget != annotation) { 
      Set<Class<? extends Annotation>> nextRevised = new HashSet<>(revised); 
      nextRevised.add(annotation); 
      result = Arrays.stream(annotation.getAnnotations()).anyMatch(a -> containsAnnotation(a.annotationType(), annotationTypeTarget, nextRevised)); 
     } 
     return result; 
    } 

    public static <T extends Annotation> boolean containsAnnotation(Class<? extends Annotation> annotation, Class<T> annotationTypeTarget) { 
     return containsAnnotation(annotation, annotationTypeTarget, Collections.emptySet()); 
    } 

    public static <T extends Annotation> Map<Class<? extends Annotation>, ? extends Annotation> getAnnotations(Method method, Class<T> annotationTypeTarget) { 
     return Arrays.stream(method.getAnnotations()).filter(a -> containsAnnotation(a.annotationType(), annotationTypeTarget)).collect(Collectors.toMap(a -> a.annotationType(), Function.identity())); 
    } 
} 

如果您有:

@Retention(RetentionPolicy.RUNTIME) 
@interface Action { 
} 

@Action 
@Retention(RetentionPolicy.RUNTIME) 
@interface SpecificAction { 
} 

@Action 
@Retention(RetentionPolicy.RUNTIME) 
@interface ParticularAction { 
} 

public class Foo{ 
    @SpecificAction 
    @ParticularAction 
    public void specificMethod() { 
     // ... 
    } 
} 

你可以使用這樣的:AnnotationUtil.getAnnotations(specificMethod, Action.class);這會返回地圖:{interface [email protected](), interface [email protected]()}

+0

這個想法確實在我的腦海中,我正在尋找一種方法來避免這樣做,而不必編寫遞歸。但正如在鏈接中所說的那樣,知道沒有這種繼承是很好的! – ldebroux