Java 클래스가 구현 된 인터페이스에서 주석을 상속하지 않는 이유는 무엇입니까?


108

나는 일부 메서드 호출을 가로 채기 위해 Guice의 AOP를 사용하고 있습니다. 내 클래스는 인터페이스를 구현하고 Guice가 올바른 메서드를 선택할 수 있도록 인터페이스 메서드에 주석을 달고 싶습니다. 주석 유형이 Inherited 주석 구현 클래스로 주석 이 달린 경우에도 Inherited의 Java 문서에 명시된 주석을 상속하지 않습니다.

또한이 메타 주석은 주석이 수퍼 클래스에서 상속되도록합니다. 구현 된 인터페이스에 대한 주석은 효과가 없습니다.

그 이유는 무엇일까요? 객체의 클래스가 런타임에 구현하는 모든 인터페이스를 아는 것은 그렇게 어려운 일이 아니므로이 결정 뒤에는 좋은 이유가 있어야합니다.

답변:


130

그 이유는 그렇지 않으면 다중 상속 문제가 발생하기 때문입니다.

예:

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

이렇게하면 :

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

결과는 어떻습니까? 'baz', 'phleem'또는 'flopp'?


이러한 이유로 인터페이스의 주석은 거의 유용하지 않습니다.


9
인터페이스에 대한 주석은이를 지원하는 프레임 워크가있는 경우에만 유용합니다. 이 예에서 BTW getAnnotation ()은 null을 반환합니다.)
Peter Lawrey 2011 년

6
모르겠어요, 여러분. 이 경우 (오타가 없으면) The field value is ambiguous.다른 값으로 동일한 상수를 선언하는 두 개의 인터페이스에서와 같이 유사한 컴파일러 오류가 발생합니다. 이것이 필드 가 아니라는 것을 알고 있지만 주석 값은 컴파일 타임에 모두 해결됩니다. 여기서 누락 된 기능은 많은 경우에 매우 유용합니다. 그건 그렇고, 오래된 게시물을 되살려 서 죄송합니다 :).
Petr Janeček 2012

7
@Slanec은 Spring 사람들이 이러한 문제를 해결하는 방법을보기 위해 Spring 소스 방식을 살펴 봅니다. 참조 AnnotationUtils.findAnnotation (방법, annotationType)
숀 패트릭 플로이드

1
나는 이것과 비슷한 것을 쓰는 것을 고려하고 있었다. 일종의 간단한 캐싱을 사용하면 이것이 나에게 맞는 방법처럼 보입니다. 감사! 위의 예에서 Foo'의 어노테이션을 찾고 ( MyClass없는 경우 인터페이스가 검색되고 뒤의 순서대로 취해집니다 implements) 따라서 "baz"를 인쇄합니다. 멋있는.
Petr Janeček 2012

2
누군가가 오타 :-) 발견하는 진정한 @WChargin, 그것은 불과 2 년이 걸렸다
숀 패트릭 플로이드

35

@Inherited에 대한 Javadoc 에서 :

주석 유형이 자동으로 상속됨을 나타냅니다. 상속 된 메타 주석이 주석 유형 선언에 있고 사용자가 클래스 선언에 대한 주석 유형을 쿼리하고 클래스 선언에이 유형에 대한 주석이없는 경우 클래스의 수퍼 클래스가 주석 유형에 대해 자동으로 쿼리됩니다. 이 프로세스는이 유형에 대한 주석을 찾거나 클래스 계층 (Object)의 최상위에 도달 할 때까지 반복됩니다. 이 유형에 대한 주석이있는 수퍼 클래스가없는 경우 쿼리는 해당 클래스에 그러한 주석이 없음을 나타냅니다. 이 메타 어노테이션 유형은 어노테이션이있는 유형이 클래스가 아닌 다른 것을 어노테이션하는 데 사용되는 경우 효과가 없습니다. 또한이 메타 주석은 주석이 수퍼 클래스에서 상속되도록합니다.

반면에 JSR 305 유효성 검사기는 일종의 상속 조회를 수행합니다. 클래스 계층이있는 경우 :

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

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

그러면에 대한 효과적인 유효성 검사 Student.getAge()@Nonnull @Min(5). 메타 주석 @Nonnull이 없습니다 @Inherited.


4
이 답변이 선택되어야합니다
Andrzej Purtak 2016 년

3
귀하의 예제는 말한다 답변, 모순 @Inherited클래스 이외에 아무런 영향을 미치지 않습니다
올렉 Mikheev를

당신이 클래스에 주석을 사용하는 경우에만 작업을 @Inherited
카를로스 파커
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.