Почему я получаю сообщение об ошибке «Значение атрибута должно быть постоянным». Разве нулевая не константа ???
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class<? extends Foo> bar() default null;// this doesn't compile
}
java
annotations
default
потрошитель234
источник
источник
Class<? extends Foo> bar();
.Ответы:
Не знаю почему, но JLS очень ясен:
Discussion Note that null is not a legal element value for any element type.
И определение элемента по умолчанию:
DefaultValue: default ElementValue
К сожалению, я продолжаю обнаруживать, что новые языковые функции (перечисления, а теперь и аннотации) содержат очень бесполезные сообщения об ошибках компилятора, когда вы не соответствуете спецификации языка.
РЕДАКТИРОВАТЬ: небольшой поиск в Google обнаружил следующее в JSR-308, где они выступают за разрешение нулей в этой ситуации:
Я думаю, что только два последних пункта имеют отношение к вопросу «почему бы не сделать это в первую очередь». Последний пункт, безусловно, поднимает хороший вопрос - обработчик аннотаций никогда не должен беспокоиться о том, что он получит нулевое значение для значения аннотации. Я склонен видеть, что обработка аннотаций и другой подобный фреймворк требует большей работы, чем выполнение такой проверки, чтобы сделать код разработчиков более понятным, а не наоборот, но это определенно затруднит оправдание его изменения.
источник
Попробуй это
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SomeInterface { Class bar() default void.class; }
Для этого не требуется новый класс, и это уже ключевое слово в Java, которое ничего не значит.
источник
Class<? extends Foo> bar() default void.null
не компилируется.Казалось бы, это незаконно, хотя JLS очень расплывчато об этом.
Я напряг свою память, чтобы попытаться представить существующую аннотацию, которая имеет атрибут Class для аннотации, и вспомнил эту аннотацию из JAXB API:
@Retention(RUNTIME) @Target({PACKAGE,FIELD,METHOD,TYPE,PARAMETER}) public @interface XmlJavaTypeAdapter { Class type() default DEFAULT.class; static final class DEFAULT {} }
Вы можете видеть, как им пришлось определить фиктивный статический класс для хранения эквивалента нуля.
Неприятно.
источник
Похоже, есть еще один способ сделать это.
Мне это тоже не нравится, но может сработать.
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SomeInterface { Class<? extends Foo>[] bar() default {}; }
Таким образом, вместо этого вы создаете пустой массив. Кажется, это позволяет использовать значение по умолчанию.
источник
Как уже упоминалось, спецификация языка Java не допускает пустых значений в аннотациях по умолчанию.
Я стараюсь определять
DEFAULT_VALUE
константы в верхней части определения аннотации. Что-то вроде:public @interface MyAnnotation { public static final String DEFAULT_PREFIX = "__class-name-here__ default"; ... public String prefix() default DEFAULT_PREFIX; }
Затем в своем коде я делаю что-то вроде:
if (myAnnotation.prefix().equals(MyAnnotation.DEFAULT_PREFIX)) { ... }
В вашем случае с классом я бы просто определил класс маркера. К сожалению, у вас не может быть константы для этого, поэтому вместо этого вам нужно сделать что-то вроде:
public @interface MyAnnotation { public static Class<? extends Foo> DEFAULT_BAR = DefaultBar.class; ... Class<? extends Foo> bar() default DEFAULT_BAR; }
Ваш
DefaultFoo
класс будет просто пустой реализацией, чтобы код мог:if (myAnnotation.bar() == MyAnnotation.DEFAULT_BAR) { ... }
Надеюсь это поможет.
источник
.equals()
а не==
@Doradus? Вы получили другое значение или другой объект.==
..equals()
. Удивительно.Это сообщение об ошибке вводит в заблуждение, но, нет,
null
буквальным не является постоянным выражением, как определено в спецификации языка Java, здесь .Кроме того, в спецификации языка Java говорится
И объяснить, что это значит
Итак, здесь тип вашего элемента,
Class<? extends Foo>
не соизмерим со значением по умолчанию, потому что это значение равноnull
.источник
or
и внутреннееand
, о которых нельзя забывать.Как говорили другие, существует правило, согласно которому null не является допустимым значением по умолчанию в Java.
Если у вас есть ограниченное количество возможных значений, которые может иметь поле , то один из вариантов решения этой проблемы - сделать тип поля настраиваемым перечислением, которое само содержит сопоставление с нулевым значением. Например, представьте, что у меня есть следующая аннотация, для которой мне нужен ноль по умолчанию:
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; }
Основным недостатком этого (помимо необходимости перечислять возможные значения) является то, что теперь вы заключили свое значение в перечисление, поэтому вам нужно будет вызвать свойство / геттер перечисления, чтобы получить значение.
источник