Java에서 주석을 확장 할 수없는 이유는 무엇입니까?


227

Java 클래스와 마찬가지로 Java 주석에 상속이없는 이유를 이해하지 못합니다. 나는 그것이 매우 유용 할 것이라고 생각합니다.

예를 들어 : 주어진 주석이 유효성 검사기인지 알고 싶습니다. 상속을 통해 수퍼 클래스를 반복적으로 탐색하여이 주석이 ValidatorAnnotation. 그렇지 않으면 어떻게 할 수 있습니까?

그렇다면 누구나이 디자인 결정의 이유를 말해 줄 수 있습니까?


2
BTW는 모든 주석이 확장된다는 점에 유의하십시오. java.lang.annotation.Annotation즉, instanceof이 사실은 명시 적으로 선언되지 않았지만 주석입니다 .
Tomáš Záluský

답변:


166

그렇게 설계되지 않은 이유에 대해서는 JSR 175 Design FAQ 에서 답변을 찾을 수 있습니다 .

어노테이션 서브 타이핑을 지원하지 않는 이유는 무엇입니까 (한 어노테이션 유형이 다른 어노테이션 유형을 확장하는 경우)?

주석 유형 시스템을 복잡하게 만들고“특정 도구”를 작성하기가 훨씬 어렵습니다.

“특정 도구”— 알려진 외부 유형의 임의 외부 프로그램을 쿼리하는 프로그램. 예를 들어 스텁 생성기는이 범주에 속합니다. 이러한 프로그램은 가상 시스템으로로드하지 않고 주석이 달린 클래스를 읽지 만 주석 인터페이스를로드합니다.

네, 그 이유는 단지 KISS 일 것입니다. 어쨌든이 문제 (다른 많은 것들과 함께)가 JSR 308의 일부로 고려되고있는 것처럼 보이며 Mathias Ricken 이 이미 개발 한이 기능을 가진 대체 컴파일러를 찾을 수도 있습니다 .


67
글쎄요, 어리석은 일이지만 "간단하게 유지"하기 위해 주석을 확장 할 수는 없습니다. 적어도 자바 디자이너들은 클래스 상속에 대해 똑같이 생각하지 않았다. : P
sinuhepop

2
Java 8 M7은 하위 클래스 주석을 지원하지 않는 것 같습니다. 아쉽습니다.
Ceki

2
@assylias JEP 104는 주석을 서브 클래 싱 할 수 있도록하는 것이 아닙니다. JEP 104는 Java 8에서 구현되었지만 여전히 주석을 서브 클래 싱 할 수 없습니다 (한 주석이 다른 주석을 확장하도록 함).
Jesper

71

확장 가능한 주석은 다른 유형 시스템을 지정하고 유지해야하는 부담을 효과적으로 가중시킵니다. 이것은 상당히 독특한 유형의 시스템이므로 OO 유형 패러다임을 적용 할 수 없습니다.

주석에 다형성 및 상속을 도입 할 때 모든 문제를 고려하십시오 (예 : 하위 주석이 보유와 같은 메타 주석 사양을 변경하면 어떻게됩니까?)

그리고이 모든 것이 어떤 유스 케이스에 복잡성을 더했습니까?

주어진 주석이 카테고리에 속하는지 알고 싶습니까?

이 시도:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    String category();
}

@Category(category="validator")
public @interface MyFooBarValidator {

}

보시다시피 제공된 기능을 사용하여 과도한 고통없이 주석을 쉽게 그룹화하고 분류 할 수 있습니다.

따라서 KISS 는 메타 유형 시스템을 Java 언어에 도입하지 않은 이유입니다.

[ps 편집]

나는 데모를 위해 개방형 메타 주석을보기 위해 단순히 String을 사용했습니다. 자신이 지정한 프로젝트의 경우 분명히 범주 유형의 열거 형을 사용하고 주어진 주석에 여러 범주 ( "다중 상속")를 지정할 수 있습니다. 값은 전적으로 가짜이며 데모 목적으로 만 사용됩니다.

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    AnnotationCategory[] category();
}
public enum AnnotationCategory {
    GENERAL,
    SEMANTICS,
    VALIDATION,
    ETC
}

@Category(category={AnnotationCategory.GENERAL, AnnotationCategory.SEMANTICS})
public @interface FooBarAnnotation {

}


작동하지 않습니다. false를 인쇄합니다.@Target(ElementType.ANNOTATION_TYPE) @Retention(RetentionPolicy.RUNTIME) @interface C {}; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @C public @interface F {} class a{ @F public void S() {} } @Test public void blahTest() throws NoSuchMethodException { Method m = a.class.getMethod("S"); System.out.println(m.isAnnotationPresent(C.class)); }
user1615664

주석에 주석을 달고 있습니다. a # S에는 주석 F가 있습니다. F 자체에는 C로 주석이 달렸습니다. 사용해보십시오.
alphazero

네 맞습니다. 그러나 Annotation 프록시를 읽는 것보다 더 깨끗하게하는 방법이 있습니까?
user1615664

12

어떤 의미에서 이미 주석-메타 주석이 있습니다. 메타 정보로 주석에 주석을 달면 여러 가지 방법으로 추가 인터페이스를 확장하는 것과 같습니다. 어노테이션은 인터페이스이므로 다형성이 실제로 작동하지 않으며 실제로 정적이므로 런타임 동적 디스패치가 불가능합니다.

유효성 검사기 예제에서 주석에 주석이 달린 유형을 가져 와서 유효성 검사기 메타 주석이 있는지 확인할 수 있습니다.

상속이 도움이 될 수있는 유일한 유스 케이스는 수퍼 유형별로 주석을 얻을 수 있기를 원하지만 주어진 메소드 또는 유형에 두 개의 주석이있을 수 있기 때문에 많은 복잡성이 추가됩니다. 즉, 단일 객체 대신 배열을 반환해야합니다.

따라서 궁극적 인 대답은 유스 케이스가 난해하고 더 표준적인 유스 케이스를 복잡하게하여 가치가 없다는 것입니다.


5

Java 어노테이션 지원 설계자는 Java 커뮤니티에 해를 끼치는 여러 가지 "단순화"를 작성했습니다.

  1. 주석이없는 하위 유형은 많은 복잡한 주석을 불필요하게 추악하게 만듭니다. 어노테이션 내에 단순히 세 가지 중 하나를 보유 할 수있는 속성을 가질 수 없습니다. 하나는 세 가지 별도의 특성을 가져야하며, 이는 개발자를 혼란스럽게하며 세 가지 중 하나만 사용되도록 런타임 유효성 검증이 필요합니다.

  2. 사이트 당 하나의 지정된 유형의 주석 만 이로 인해 완전히 불필요한 컬렉션 주석 패턴이 생겼습니다. @Validation 및 @Validations, @Image 및 @Images 등

두 번째는 Java 8에서 수정되었지만 너무 늦었습니다. 많은 프레임 워크가 Java 5에서 가능한 것을 기반으로 작성되었으며 이제는 이러한 API 사마귀가 오랫동안 오랫동안 머물러 있습니다.


1
뿐만 아니라 XML 스키마에서 지원하는 재귀 적으로 중첩 된 속성이있는 속성을 정의 할 수 없습니다. 이로 인해 주석은 XML보다 훨씬 덜 강력합니다.
user2833557

3

이 질문에 답하는 데 3 년이 늦었을 수도 있지만 같은 장소에서 자신을 발견했기 때문에 흥미로 웠습니다. 여기에 내가 가져 가라. 주석을 열거 형으로 볼 수 있습니다. 단방향 정보를 제공합니다. 사용하거나 잃어 버립니다.

웹 응용 프로그램에서 GET, POST, PUT 및 DELETE를 시뮬레이트하려는 상황이있었습니다. "HTTP_METHOD"라는 "슈퍼"주석을 갖고 싶었습니다. 나중에 중요하지 않다는 생각이 들었습니다. 글쎄, DELETE와 PUT을 식별하기 위해 HTML 양식에 숨겨진 필드를 사용하여 정착해야했습니다 (POST와 GET이 가능했기 때문에).

서버 측에서 이름이 "_method"인 숨겨진 요청 매개 변수를 찾았습니다. 값이 PUT 또는 DELETE 인 경우 연관된 HTTP 요청 메소드를 대체합니다. 그럼에도 불구하고 작업을 완료하기 위해 주석을 확장 해야하는지 여부는 중요하지 않았습니다. 모든 주석은 동일하게 보이지만 서버 측에서는 다르게 취급되었습니다.

따라서 귀하의 경우 가려움증을 떨어 뜨려 주석을 확장하십시오. 그것들을 '마커'로 취급하십시오. 그것들은 어떤 정보를“표현”하며 반드시 어떤 정보를“조작”할 필요는 없습니다.


2

내가 생각할 수있는 한 가지는 여러 주석을 가질 수 있다는 것입니다. 따라서 동일한 위치에 유효성 검사기와보다 구체적인 주석을 추가 할 수 있습니다. 그러나 나는 착각 할 수있다 :)


2

그것에 대해 결코 생각하지 않았지만 ... 당신이 옳은 것처럼 보입니다. 주석 상속 기능에는 문제가 없습니다 (적어도 나는 그것에 문제가 보이지 않습니다).

'유효성 검사기' 주석이 포함 된 예제 정보 - '메타 주석' 접근법을 활용할 수 있습니다 . 즉, 특정 메타 주석을 전체 주석 인터페이스에 적용합니다.


이 질문에 답하는 데 3 년이 늦었을 수도 있지만 같은 장소에서 자신을 발견했기 때문에 흥미로 웠습니다.
mainas

1

내가 가진 동일한 문제. 아냐, 못해 나는 몇 가지 표준을 존중하기 위해 주석에 속성을 작성하도록 나 자신을 '훈련'했습니다. 따라서 주석을 얻을 때 외부에서 속성으로 어떤 종류의 주석을 스니핑 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.