Атрибут Annotation должен быть литералом класса? Зачем? Константы тоже должны быть хорошими
Может кто-нибудь объяснить, почему параметры аннотации String и Class ожидаются по-разному? Почему компилятор требует литералов для классов, если также принимать константы для строк?
Рабочий пример с Spring @RequestMapping:
public class MyController {
public static final String REQUEST_MAPPING = "/index.html";
@RequestMapping(MyController.REQUEST_MAPPING) // ALL OK!
...
}
Пример WTF с TestNG @Test:
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.class). Но почему? Единственное отличие в параметре аннотации, которое я вижу, это его тип: String vs Class. Почему бы компилятор Java не принимал константу String, но принимал только литералы класса?
Ответы
Ответ 1
Спецификация языка Java не позволяет использовать константы времени компиляции с параметрами типа Class
. Вы можете использовать только литералы класса.
JLS имеет следующие значения подходящих значений параметров для аннотаций:
Тип элемента T соизмерим с значением элемента V тогда и только тогда, когда выполняется одно из следующих условий:
- T - тип массива E [] и либо:
- V является ElementValueArrayInitializer, и каждый ElementValueInitializer (аналогичный инициализатору переменной в инициализаторе массива) в V соизмерим с E. Or
- V - элемент ElementValue, соизмеримый с T.
- Тип V является совместимым присваиванием (§5.2) с T и, кроме того:
- Если T является примитивным типом или строкой, V является константным выражением (§15.28).
- V не является нулевым.
- , если T является классом или вызовом класса, а V является литералом класса (§15.8.2).
- Если T - тип перечисления, а V - константа перечисления.
Это ошибка времени компиляции, если тип элемента не соразмерен с ElementValue.
Я не могу сказать, почему это ограничение находится в JLS.
Ответ 2
Я получил значение аннотации, которое должно быть литералом класса:
@ServerEndpoint(value="/story/notifications",
encoders = (StickerEncoder.class),
decoders = (StickerDecoder.class))
Это происходит, следуя одному из уроков Оракула на веб-сайтах. Оказывается, видео не является качеством 720p, а нечеткость скрывает фигурные скобки, которые выглядят как фигурные скобки. Таким образом, ошибка исчезает при изменении скобок (скобок) для фигурных скобок.
@ServerEndpoint(value="/story/notifications",
encoders = {StickerEncoder.class},
decoders = {StickerDecoder.class})
hth любой, кто может путешествовать по тому же в будущем.
Ответ 3
Посмотрите:
public static final Class TEST_EXCEPTION = RuntimeException.class;
Класс должен быть Throwable, который компилятор может проверить. Итак, попробуйте следующее:
public static final Class<? extends Throwable> TEST_EXCEPTION = RuntimeException.class;
Ответ 4
Комната не имеет встроенной поддержки для хранения дат, вам нужно преобразовать ее в значения LONG при вставке и чтении в базу данных и из нее. Следовательно, мы несем ответственность за указание базы данных Room, как конвертировать данные
Для этого, благодаря архитектуре помещения, у нас есть класс TypeConverter. Ну, не увлекайтесь, нет специального класса, который вы можете просто расширить и выполнить, но это то, что вы должны написать с нуля, но он использует аннотации, чтобы он работал с 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 {...}
Вы готовы к рок!
Ответ 5
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