Атрибут Annotation должен быть литералом класса? Почему? Константы тоже должны быть в порядке

может кто-нибудь объяснить, почему параметры аннотаций строк и классов ожидаются по-разному? Почему компилятор требует литералов для классов, а также принимает константы для строк?

рабочий пример с @RequestMapping весны:

public class MyController {
    public static final String REQUEST_MAPPING = "/index.html";
    @RequestMapping(MyController.REQUEST_MAPPING) // ALL OK!
    ...
}

ВТФ пример с @тест для TestNG это:

public class MyControllerTest {
    public static final Class TEST_EXCEPTION = RuntimeException.class;
    @Test(expectedExceptions = MyControllerTest.TEST_EXCEPTION) // compilation error, WTF:
    // The value for annotation attribute Test.expectedExceptions must be a class literal
    ...
}

конечно, работает @Test (expectedExceptions = RuntimeException.класс.) Но почему? Разница только в параметре аннотации я вижу его тип: String vs Class. Почему компилятор Java также принимает строковую константу, но принимает только литералы классов?

3 ответов


спецификация языка Java не позволяет использовать константы времени компиляции с параметрами типа Class. Можно использовать только литералы классов.

на JLS имеет следующее, чтобы сказать о подходящих значениях параметров для аннотаций:

тип элемента T соответствует значению элемента V если и только если выполняется одно из следующих условий:

  • T является типом массива E[] и:
    • V это ElementValueArrayInitializer и друг ElementValueInitializer (аналогично инициализатору переменной в инициализаторе массива) в V соизмерима с E. Или
    • V это ElementValue в соответствии с T.
  • тип V совместимо ли назначение (§5.2) С T и, кроме того:
    • если T является примитивным типом или строкой,V является постоянным выражением (§15.28).
    • V не null.
    • если T является классом или вызовом класса, А V-литералом класса (§15.8.2).
    • если T является типом перечисления, и V является перечислимой константой.

Это-ошибка времени компиляции, если тип элемента не соответствует ElementValue.

Я не могу сказать, почему это ограничение находится в JLS.


Я получил "значение аннотации должно быть литералом класса" на следующем:

@ServerEndpoint(value="/story/notifications",
        encoders = (StickerEncoder.class),
        decoders = (StickerDecoder.class))

это происходит, следуя одному из учебников оракулов на websockets. Оказывается, видео не является качеством 720p, и нечеткость скрывает фигурные скобки, которые выглядят как фигурные скобки. Таким образом, ошибка исчезает при изменении скобок (скобок) для фигурных скобок.

@ServerEndpoint(value="/story/notifications",
        encoders = {StickerEncoder.class},
        decoders = {StickerDecoder.class})

hth любой, кто может споткнуться о то же самое в будущем.


выглядеть так:

public static final Class TEST_EXCEPTION = RuntimeException.class;

класс должен быть Throwable, который компилятор может проверить. Итак, попробуйте следующее:

public static final Class<? extends Throwable> TEST_EXCEPTION = RuntimeException.class;