Что выведет следующий код?
Anonymous Quiz
20%
000111222
18%
012012012
2%
010120212
60%
Все варианты правильные
👍22🌚4
Для чего используются аннотации?
Удобно рассмотреть случаи применения аннотаций с точки зрения возможных значений их свойства RetentionPolicy:
SOURCE – аннотация присутствует только в исходном коде, но не вовлечена в компиляцию. Можно разделить их на две категории:
Первая – аннотации для программиста, а не для программы. Это всевозможные маркеры. Они добавляют аннотируемым элементам некоторую специальную семантику. Более формализованный вариант документации. Примеры – @Immutable и @ThreadSafe из Hibernate.
Вторая категория – инструкции для инструментов разработки. Примеры этой категории, @SuppressWarnings и @Override могут влиять на предупреждения и ошибки компиляции. IntelliJ IDEA умеет понимать @Nullable и @NonNull из Spring Framework, и предупреждать о возможных NullPointerException.
CLASS – самое экзотическое, но при том стандартное значение. Аннотация попадает в байткод .class-файла, но игнорируется загрузчиком классов. В результате такая аннотация недоступна для рефлекшна. Используется для сторонних инструментов, обрабатывающих байткод, например для обфускаторов.
RUNTIME – самое ходовое значение. Цель снабжается метаинформацией, доступной во время выполнения программы. Сама по себе аннотация всё так же не добавляет нового поведения. Для практической пользы runtime-аннотации в программе должен быть исполнен некоторый код процессинга, который прочитает метаинформацию инструментами Reflection API. Такой механизм широко используется во множестве популярных фреймворков: Spring, Hibernate, Jackson.
Удобно рассмотреть случаи применения аннотаций с точки зрения возможных значений их свойства RetentionPolicy:
SOURCE – аннотация присутствует только в исходном коде, но не вовлечена в компиляцию. Можно разделить их на две категории:
Первая – аннотации для программиста, а не для программы. Это всевозможные маркеры. Они добавляют аннотируемым элементам некоторую специальную семантику. Более формализованный вариант документации. Примеры – @Immutable и @ThreadSafe из Hibernate.
Вторая категория – инструкции для инструментов разработки. Примеры этой категории, @SuppressWarnings и @Override могут влиять на предупреждения и ошибки компиляции. IntelliJ IDEA умеет понимать @Nullable и @NonNull из Spring Framework, и предупреждать о возможных NullPointerException.
CLASS – самое экзотическое, но при том стандартное значение. Аннотация попадает в байткод .class-файла, но игнорируется загрузчиком классов. В результате такая аннотация недоступна для рефлекшна. Используется для сторонних инструментов, обрабатывающих байткод, например для обфускаторов.
RUNTIME – самое ходовое значение. Цель снабжается метаинформацией, доступной во время выполнения программы. Сама по себе аннотация всё так же не добавляет нового поведения. Для практической пользы runtime-аннотации в программе должен быть исполнен некоторый код процессинга, который прочитает метаинформацию инструментами Reflection API. Такой механизм широко используется во множестве популярных фреймворков: Spring, Hibernate, Jackson.
👍22🌭1
Можно ли наследовать аннотацию?
Можно понять этот вопрос по-разному. Если имеется в виду, передается ли аннотация класса-родителя классу-наследнику, ответ – по умолчанию нет. Но наследование можно включить, если на объявлении аннотации поставить мета-аннотацию @Inherited. Это работает только для классов, переопределенные методы нужно аннотировать заново.
Другой возможный смысл вопроса – наследование самих типов-аннотаций. Аннотация, как класс или интерфейс представляется в системе ссылочным типом, она тоже компилируется в .class-файл. Вы можете создать переменную с типом, скажем, java.lang.Override.
Но в отличие от других ссылочных типов, объявление аннотации (@interface) не может иметь секций extends или implements. Это ограничение добавлено просто чтобы не усложнять систему типов. В скомпилированном коде все типы-аннотации – это интерфейсы, унаследованные от Annotation.
Можно понять этот вопрос по-разному. Если имеется в виду, передается ли аннотация класса-родителя классу-наследнику, ответ – по умолчанию нет. Но наследование можно включить, если на объявлении аннотации поставить мета-аннотацию @Inherited. Это работает только для классов, переопределенные методы нужно аннотировать заново.
Другой возможный смысл вопроса – наследование самих типов-аннотаций. Аннотация, как класс или интерфейс представляется в системе ссылочным типом, она тоже компилируется в .class-файл. Вы можете создать переменную с типом, скажем, java.lang.Override.
Но в отличие от других ссылочных типов, объявление аннотации (@interface) не может иметь секций extends или implements. Это ограничение добавлено просто чтобы не усложнять систему типов. В скомпилированном коде все типы-аннотации – это интерфейсы, унаследованные от Annotation.
👍22
Какой результат выведет следующая программа?
Anonymous Quiz
41%
A is equal to Infinity
24%
A is equal to NaN
19%
Ошибку при выполнении
17%
Ошибку компиляции
👍21🥴2⚡1🔥1🤔1
Можно ли добавить одному элементу несколько одинаковых аннотаций?
По умолчанию нельзя. До Java 8 нужно было создавать дополнительную аннотацию-контейнер, в ней в виде проперти объявлять массив интересующих аннотаций. При применении набор аннотаций нужно было оборачивать в этот контейнер (см. на картинке).
Начиная с Java 8 в стандартную библиотеку добавлена мета-аннотация @Repeatable.
Механизм ее действия такой же, как раньше: помечая ей интересующую аннотацию, необходимо указать параметром @Repeatable аннотацию-контейнер. Нововведение заключается в синтаксисе использования: теперь набор аннотаций оборачивается в контейнер неявно.
Со стороны Reflection при чтении мета-информации тоже появилась возможность не оперировать контейнером явно – метод getAnnotationsByType при необходимости найдет и развернет этот контейнер.
По умолчанию нельзя. До Java 8 нужно было создавать дополнительную аннотацию-контейнер, в ней в виде проперти объявлять массив интересующих аннотаций. При применении набор аннотаций нужно было оборачивать в этот контейнер (см. на картинке).
Начиная с Java 8 в стандартную библиотеку добавлена мета-аннотация @Repeatable.
Механизм ее действия такой же, как раньше: помечая ей интересующую аннотацию, необходимо указать параметром @Repeatable аннотацию-контейнер. Нововведение заключается в синтаксисе использования: теперь набор аннотаций оборачивается в контейнер неявно.
Со стороны Reflection при чтении мета-информации тоже появилась возможность не оперировать контейнером явно – метод getAnnotationsByType при необходимости найдет и развернет этот контейнер.
👍11🔥1
Какой результат будет получен после компиляции и выполнения данного кода?
Anonymous Quiz
7%
a test A
24%
a test B
6%
b test A
45%
b test B
5%
b test A test B
3%
Ошибка выполнения
10%
Ошибка компиляции
👍27
Какие у аннотации бывают таргеты?
Мета-аннотация @Target определяет, в каком контексте может применяться объявляемая аннотация. Допустимые контексты перечисляются значениями ElementType. По умолчанию, если @Target не указан, разрешены все контексты кроме TYPE_PARAMETER. Возможные таргеты:
• TYPE – Объявление класса, интерфейса, аннотации или enum-а.
• FIELD – Объявление поля (включая константы enum-ов).
• METHOD – Объявление метода.
• PARAMETER – Формальный параметр в объявлении метода.
• CONSTRUCTOR – Объявление конструктора.
• LOCAL_VARIABLE – Объявление локальной переменной.
• ANNOTATION_TYPE – Объявление аннотации. Применяется для создания мета-аннотации.
• PACKAGE – Объявление пакета (в package-info.java).
–– С Java 8 ––
• TYPE_PARAMETER – Обявление generic типа-параметра.
• TYPE_USE – Любое использование типа. Например приведение: (@NonNull String) myObject.
–– С Java 9 ––
• MODULE – Объявление модуля.
Мета-аннотация @Target определяет, в каком контексте может применяться объявляемая аннотация. Допустимые контексты перечисляются значениями ElementType. По умолчанию, если @Target не указан, разрешены все контексты кроме TYPE_PARAMETER. Возможные таргеты:
• TYPE – Объявление класса, интерфейса, аннотации или enum-а.
• FIELD – Объявление поля (включая константы enum-ов).
• METHOD – Объявление метода.
• PARAMETER – Формальный параметр в объявлении метода.
• CONSTRUCTOR – Объявление конструктора.
• LOCAL_VARIABLE – Объявление локальной переменной.
• ANNOTATION_TYPE – Объявление аннотации. Применяется для создания мета-аннотации.
• PACKAGE – Объявление пакета (в package-info.java).
–– С Java 8 ––
• TYPE_PARAMETER – Обявление generic типа-параметра.
• TYPE_USE – Любое использование типа. Например приведение: (@NonNull String) myObject.
–– С Java 9 ––
• MODULE – Объявление модуля.
🔥10👍2
Какой результат выполнения данной части кода?
Anonymous Quiz
14%
1
62%
2
5%
Ошибка времени выполнения
20%
Ошибка компиляции
👍8
Как используется @Deprecated?
Этой аннотацией помечают код, который устарел и не должен быть более использован. Классы, которые используют или переопределяют @Deprecated элементы, будут компилироваться с warning-ом.
Имеет retention RUNTIME, что значит, что фреймворки могут динамически проверять наличие аннотации на элементе с помощью Reflection API.
Начиная с Java 9 у этой аннотации появились опциональные параметры – строка since и булево значение forRemoval. В since указывается версия вашего приложения, начиная с которой элемент считается устаревшим. Значение true в forRemoval предупреждает, что со следующей мажорной версии этот элемент будет удален. Такое нововведение связано с изменением политики устаревания – с Java 9 и устаревшие элементы самой JDK тоже могут удаляться в будущих версиях.
Обычно, когда элемент помечают устаревшим, причины устаревания и дальнейшие рекомендации указывают в его Javadoc-документации под тегом @deprecated.
Этой аннотацией помечают код, который устарел и не должен быть более использован. Классы, которые используют или переопределяют @Deprecated элементы, будут компилироваться с warning-ом.
Имеет retention RUNTIME, что значит, что фреймворки могут динамически проверять наличие аннотации на элементе с помощью Reflection API.
Начиная с Java 9 у этой аннотации появились опциональные параметры – строка since и булево значение forRemoval. В since указывается версия вашего приложения, начиная с которой элемент считается устаревшим. Значение true в forRemoval предупреждает, что со следующей мажорной версии этот элемент будет удален. Такое нововведение связано с изменением политики устаревания – с Java 9 и устаревшие элементы самой JDK тоже могут удаляться в будущих версиях.
Обычно, когда элемент помечают устаревшим, причины устаревания и дальнейшие рекомендации указывают в его Javadoc-документации под тегом @deprecated.
👍17
Даны следующие классы:
Anonymous Quiz
5%
Исключение RuntimeException.
52%
Исключение ClassCastException.
24%
Успешный запуск и отработка.
19%
Ошибка компиляции.
👍31🍌1
Перечислите все мета-аннотации
Мета-аннотации – это аннотации для объявления других аннотаций. Вообще мета-аннотациями можно назвать любую аннотацию с таргетом ANNOTATION_TYPE, но основных в Java существует 5. Они определяют для аннотации:
• @Retention – переживет ли компиляцию.
• @Inherited – применяется к наследникам.
• @Repeatable – применяема несколько раз к одному и тому же элементу.
• @Target – контексты, в которых можно применять.
• @Deprecated – не должна использоваться.
Мета-аннотации – это аннотации для объявления других аннотаций. Вообще мета-аннотациями можно назвать любую аннотацию с таргетом ANNOTATION_TYPE, но основных в Java существует 5. Они определяют для аннотации:
• @Retention – переживет ли компиляцию.
• @Inherited – применяется к наследникам.
• @Repeatable – применяема несколько раз к одному и тому же элементу.
• @Target – контексты, в которых можно применять.
• @Deprecated – не должна использоваться.
👍22🕊2❤1
Что выведет на экран следующий код?
Anonymous Quiz
55%
Tt.iss.onethodA 1
15%
Tt.iss.onethodA 2
10%
Tt.iss.onethodA 0
7%
Ошибка выполнения
14%
Ошибка компиляции
👍24❤4
Что такое Type Erasure?
Компилятор удаляет из байткода класс-файла информацию о типах-дженериках. Этот процесс и называется стирание типов (type erasure). Он появился в Java 5 вместе с самими дженериками. Такое решение позволило сохранить обратную совместимость без перекомпилляции кода Java 4.
Стирание состоит из трех действий:
🔘 Если параметры ограничены (bounded), вместо типа-параметра в местах использования подставляется верхняя граница, иначе Object;
🔘 В местах присвоения значения типа-параметра в переменную обычного типа добавляется каст к этому типу;
🔘 Генерируются bridge-методы.
Информация о типах стирается только из методов и полей, но остается в метаинформации самого класса. Получить эту информацию в рантайме можно с помощью рефлекшна, методом Field#getGenericType.
Тип со стертой информацией о дженериках называется «Non-reifiable».
Стирание типов позволяет не создавать при применении дженериков новые классы, в отличие от, например, шаблонов C++.
Компилятор удаляет из байткода класс-файла информацию о типах-дженериках. Этот процесс и называется стирание типов (type erasure). Он появился в Java 5 вместе с самими дженериками. Такое решение позволило сохранить обратную совместимость без перекомпилляции кода Java 4.
Стирание состоит из трех действий:
🔘 Если параметры ограничены (bounded), вместо типа-параметра в местах использования подставляется верхняя граница, иначе Object;
🔘 В местах присвоения значения типа-параметра в переменную обычного типа добавляется каст к этому типу;
🔘 Генерируются bridge-методы.
Информация о типах стирается только из методов и полей, но остается в метаинформации самого класса. Получить эту информацию в рантайме можно с помощью рефлекшна, методом Field#getGenericType.
Тип со стертой информацией о дженериках называется «Non-reifiable».
Стирание типов позволяет не создавать при применении дженериков новые классы, в отличие от, например, шаблонов C++.
👍28❤1❤🔥1