「属性値は定数でなければなりません」というエラーが表示されるのはなぜですか。null定数じゃないの???
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class<? extends Foo> bar() default null;// this doesn't compile
}
「属性値は定数でなければなりません」というエラーが表示されるのはなぜですか。null定数じゃないの???
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class<? extends Foo> bar() default null;// this doesn't compile
}
これを試して
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class bar() default void.class;
}
新しいクラスを必要とせず、Java ではすでに何の意味もないキーワードになっています。
JLS はこれについて非常にあいまいですが、これは違法であるように思われます。
私は自分の記憶をかき乱し、注釈への Class 属性を持つ既存の注釈を考えてみました。そして、JAXB API からこれを思い出しました。
@Retention(RUNTIME) @Target({PACKAGE,FIELD,METHOD,TYPE,PARAMETER})
public @interface XmlJavaTypeAdapter {
Class type() default DEFAULT.class;
static final class DEFAULT {}
}
null と同等のものを保持するためにダミーの静的クラスを定義する必要があったことがわかります。
不快。
やり方は他にもあるようです。
私もこれは好きではありませんが、うまくいくかもしれません。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class<? extends Foo>[] bar() default {};
}
したがって、基本的には代わりに空の配列を作成します。これはデフォルト値を許可しているようです。
他の人が言ったように、Java では null は有効なデフォルト値ではないという規則があります。
フィールドが持つことができる値の数が限られている場合、これを回避するための 1 つのオプションは、フィールド タイプを、それ自体が null へのマッピングを含むカスタム列挙型にすることです。たとえば、デフォルトの null が必要な次の注釈があるとします。
public @interface MyAnnotation {
Class<?> value() default null;
}
私たちが確立したように、これは許可されていません。代わりにできることは、列挙型を定義することです。
public enum MyClassEnum {
NULL(null),
MY_CLASS1(MyClass1.class),
MY_CLASS2(MyClass2.class),
;
public final Class<?> myClass;
MyClassEnum(Class<?> aClass) {
myClass = aClass;
}
}
注釈を次のように変更します。
public @interface MyAnnotation {
MyClassEnum value() default MyClassEnum.NULL;
}
これの主な欠点 (考えられる値を列挙する必要があることは別として) は、値を列挙型でラップしたため、列挙型でプロパティ/ゲッターを呼び出して値を取得する必要があることです。