Атрибут аннотации должен быть литералом класса?Зачем?Константы тоже должны быть в порядке - PullRequest
10 голосов
/ 22 декабря 2011

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

Рабочий пример с Spring'sReReestMapping:

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

Пример WTF с @ Test 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 (Ожидаемые исключения = RuntimeException.class). Но почему? Единственное отличие в параметре аннотации, которое я вижу, это его тип: String vs Class. С какой стати компилятор Java также принимает константу String, но принимает только литералы класса?

Ответы [ 5 ]

8 голосов
/ 22 декабря 2011

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

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

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

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

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

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

2 голосов
/ 22 февраля 2014

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

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

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

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

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

0 голосов
/ 14 мая 2019
    maven {
        url 'https://maven.google.com'
    }

Вы должны вставить это в свой проект build.gradle (Project: MyApplication (Project Name))

implementation 'android.arch.persistence.room:runtime:1.1.1'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'

Вы должны вставить это в свой проект build.gradle (Модуль: приложение)

Возможна проблема с зависимостями или просто с их именами.

Если вы хотите полный пример кода, перейдите по ссылке:

https://www.captechconsulting.com/blogs/android-architecture-components-room-persistence-library

0 голосов
/ 24 ноября 2018

Комната не имеет встроенной поддержки для хранения дат , вам необходимо преобразовать ее в значения LONG при вставке и чтении в базу данных и из нее.Следовательно, мы несем ответственность за указание в базе данных Room, как преобразовывать данные.

Для этого, благодаря архитектуре помещения, у нас есть TypeConverter class.Ну, не увлекайтесь, не существует специального класса, который вы можете просто расширить и выполнить, но это то, что вы должны написать с нуля, но он использует аннотации, чтобы он работал с Room.

Например, при работе с датами:

import android.arch.persistence.room.TypeConverter;
import java.util.Date;

//Type-Converter Class for Room
public class DateConverter {
    @TypeConverter
    // Long value to Date value
    public static Date toDate(Long timestamp) {
        return timestamp == null ? null : new Date(timestamp);
    }

    @TypeConverter
    // Date value to Long value
    public static Long toTimestamp(Date date) {
        return date == null ? null : date.getTime();
    }
}

Теперь мы должны указать нашему классу базы данных использовать этот класс TypeConverter, используя @ TypeConverters (убедитесь, что используется множественная версия).

@Database(entities = {Entity.class}, version = 1)
@TypeConverters(DateConverter.class)
public abstract class AppDatabase extends RoomDatabase {...}    

Вы готовы качаться!

0 голосов
/ 22 декабря 2011

Посмотри это:

public static final Class TEST_EXCEPTION = RuntimeException.class;

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

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