回答:
このように設計されていない理由については、JSR 175設計FAQで答えを見つけることができます。
アノテーションのサブタイピング(あるアノテーションタイプが別のアノテーションタイプを拡張する)をサポートしないのはなぜですか?
これは注釈型システムを複雑にし、「特定のツール」を書くことをはるかに困難にします。
…
「特定のツール」—任意の外部プログラムの既知の注釈タイプを照会するプログラム。たとえば、スタブジェネレータはこのカテゴリに分類されます。これらのプログラムは、注釈付きクラスを仮想マシンに読み込まずに読み取りますが、注釈インターフェイスを読み込みます。
だから、はい、私は推測します、理由はそれがただのキスであることです。とにかく、この問題は(他の多くの問題とともに)JSR 308の一部として調査されているようです。また、Mathias Rickenによってすでに開発されているこの機能を備えた代替コンパイラを見つけることもできます。
拡張可能な注釈は、別の型システムを指定および維持する負担を効果的に追加します。そして、これはかなりユニークな型システムになるので、単に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 {
}
@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)); }
ある意味では、すでにAnnotations-meta Annotationsを使用しています。メタ情報で注釈を付ける場合、それは多くの点で追加のインターフェースを拡張することと同等です。アノテーションはインターフェースであるため、ポリモーフィズムは実際には機能しません。また、アノテーションは本質的に静的であるため、実行時の動的ディスパッチはありません。
バリデーターの例では、アノテーション上でアノテーション付きタイプを取得し、バリデータメタアノテーションがあるかどうかを確認できます。
継承が役立つことがわかる唯一のユースケースは、スーパータイプでアノテーションを取得できるようにする場合ですが、特定のメソッドまたはタイプにそのようなアノテーションが2つあるため、全体の複雑さが増します。つまり、単一のオブジェクトではなく配列を返す必要があります。
したがって、最終的な答えは、ユースケースは難解であり、より標準的なユースケースが複雑になるため、価値がないということです。
Javaアノテーションサポートの設計者は、Javaコミュニティに不利益をもたらすいくつかの「単純化」を行いました。
注釈サブタイプがないと、多くの複雑な注釈が不必要に醜くなります。3つのうちの1つを保持できるアノテーション内に属性を単純に持つことはできません。1つは3つの個別の属性を持つ必要があり、開発者を混乱させ、3つのうちの1つだけが使用されることを確認するためにランタイム検証が必要です。
サイトごとに指定されたタイプの注釈は1つだけです。これにより、完全に不要なコレクションアノテーションパターンが発生します。@Validationと@ Validations、@ Imageと@Imagesなど
2つ目はJava 8で修正中ですが、手遅れです。多くのフレームワークは、Java 5で可能なことを基に作成されており、これらのAPIのいぼは、長い間ここにとどまっています。
この質問への回答は3年遅れるかもしれませんが、同じ場所にいるので興味深いと思いました。これが私の見解です。注釈を列挙として表示できます。それらは一方向の種類の情報を提供します-それを使用するか、それを失います。
WebアプリでGET、POST、PUT、DELETEをシミュレートしたい状況がありました。「HTTP_METHOD」と呼ばれる「スーパー」アノテーションが欲しいのですが。それは問題ではないことが後で私に夜明けしました。ええと、HTMLフォームの非表示フィールドを使用して、DELETEとPUTを特定する必要がありました(とにかくPOSTとGETが利用可能だったためです)。
サーバー側で、「_ method」という名前の非表示のリクエストパラメータを探しました。値がPUTまたはDELETEの場合、関連するHTTPリクエストメソッドをオーバーライドします。そうは言っても、作業を完了するためにアノテーションを拡張する必要があるかどうかは問題ではありませんでした。すべての注釈は同じように見えましたが、サーバー側では扱いが異なりました。
したがって、あなたのケースでは、注釈を拡張するためにかゆみをドロップします。それらを「マーカー」として扱います。それらは一部の情報を「表現」し、必ずしも一部の情報を「操作」するわけではありません。
それについて考えたことはありませんが...あなたの言う通りだと思いますが、アノテーションの継承機能には問題はありません(少なくとも、問題は発生しません)。
「バリデーター」アノテーションを使用した例について-悪用することができます次に「メタアノテーション」アプローチを。つまり、特定のメタ注釈を注釈インターフェイス全体に適用します。
java.lang.annotation.Annotation
が、すべての注釈が拡張されることに注意してくださいinstanceof
。