Java Интервью Вопросы Интервью (Ответы)

Java Интервью Вопросы Интервью (+ Ответы)

1. Вступление

Аннотации существуют с Java 5, и в настоящее время они представляют собой повсеместные программные конструкции, которые позволяют обогащать код.

В этой статье мы рассмотрим некоторые вопросы, касающиеся аннотаций; которые часто задают на технических собеседованиях и, при необходимости; мы будем использовать примеры, чтобы лучше понимать их ответы.

2. Вопросы

Q1. Что такое аннотации? Каковы их типичные сценарии использования?

Аннотации - это метаданные, связанные с элементами исходного кода программы и не влияющие на работу кода, с которым они работают.

Их типичные случаи использования:

  • Information for the compiler - с аннотациями компилятор может обнаруживать ошибки или подавлять предупреждения

  • Compile-time and deployment-time processing - программные инструменты могут обрабатывать аннотации и генерировать код, файлы конфигурации и т. д.

  • Runtime processing - аннотации могут быть проверены во время выполнения для настройки поведения программы

Q2. Опишите некоторые полезные аннотации из стандартной библиотеки.

В пакетахjava.lang иjava.lang.annotation есть несколько аннотаций, наиболее распространенные из которых включают, но не ограничиваются:

  • @Override – отмечает, что метод предназначен для переопределения элемента, объявленного в суперклассе. Если не удается корректно переопределить метод, компилятор выдаст ошибку

  • @Deprecated - указывает, что элемент устарел и не должен использоваться. Компилятор выдаст предупреждение, если программа использует метод, класс или поле, помеченное этой аннотацией

  • @SuppressWarnings - указывает компилятору подавлять определенные предупреждения. Чаще всего используется при взаимодействии с устаревшим кодом, написанным до появления дженериков

  • @FunctionalInterface - введено в Java 8, указывает, что объявление типа является функциональным интерфейсом и чья реализация может быть предоставлена ​​с использованием лямбда-выражения.

Q3. Как создать аннотацию?

Аннотации - это форма интерфейса, в которой ключевому словуinterface предшествует@,, а тело содержит объявленияannotation type element, которые очень похожи на методы:

public @interface SimpleAnnotation {
    String value();

    int[] types();
}

После того, как аннотация определена, вы можете начать использовать ее в своем коде:

@SimpleAnnotation(value = "an element", types = 1)
public class Element {
    @SimpleAnnotation(value = "an attribute", types = { 1, 2 })
    public Element nextElement;
}

Обратите внимание, что при предоставлении нескольких значений для элементов массива их необходимо заключать в квадратные скобки.

При желании могут быть предоставлены значения по умолчанию, если они являются константными выражениями для компилятора:

public @interface SimpleAnnotation {
    String value() default "This is an element";

    int[] types() default { 1, 2, 3 };
}

Теперь вы можете использовать аннотацию без этих элементов:

@SimpleAnnotation
public class Element {
    // ...
}

Или только некоторые из них:

@SimpleAnnotation(value = "an attribute")
public Element nextElement;

Q4. Какие типы объектов могут быть возвращены из объявления метода аннотации?

Тип возврата должен быть примитивом,String,Class,Enum, или массивом одного из предыдущих типов. В противном случае компилятор выдаст ошибку.

Вот пример кода, который успешно следует этому принципу:

enum Complexity {
    LOW, HIGH
}

public @interface ComplexAnnotation {
    Class value();

    int[] types();

    Complexity complexity();
}

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

public @interface FailingAnnotation {
    Object complexity();
}

Q5. Какие элементы программы можно аннотировать?

Аннотации могут применяться в нескольких местах по всему исходному коду. Их можно применять к объявлениям классов, конструкторов и полей:

@SimpleAnnotation
public class Apply {
    @SimpleAnnotation
    private String aField;

    @SimpleAnnotation
    public Apply() {
        // ...
    }
}

Методы и их параметры:

@SimpleAnnotation
public void aMethod(@SimpleAnnotation String param) {
    // ...
}

Локальные переменные, включая переменные цикла и ресурса:

@SimpleAnnotation
int i = 10;

for (@SimpleAnnotation int j = 0; j < i; j++) {
    // ...
}

try (@SimpleAnnotation FileWriter writer = getWriter()) {
    // ...
} catch (Exception ex) {
    // ...
}

Другие типы аннотаций:

@SimpleAnnotation
public @interface ComplexAnnotation {
    // ...
}

И даже пакеты через файлpackage-info.java:

@PackageAnnotation
package com.example.interview.annotations;

Начиная с Java 8, они также могут применяться к типамuse. Чтобы это работало, аннотация должна указывать аннотацию@Target со значениемElementType.USE:

@Target(ElementType.TYPE_USE)
public @interface SimpleAnnotation {
    // ...
}

Теперь аннотацию можно применить к созданию экземпляра класса:

new @SimpleAnnotation Apply();

Тип бросков:

aString = (@SimpleAnnotation String) something;

Реализует пункт:

public class SimpleList
  implements @SimpleAnnotation List<@SimpleAnnotation T> {
    // ...
}

И предложениеthrows:

void aMethod() throws @SimpleAnnotation Exception {
    // ...
}

Q6. Есть ли способ ограничить элементы, к которым можно применить аннотацию?

Да, для этой цели можно использовать аннотацию@Target. Если мы попытаемся использовать аннотацию в контексте, где она неприменима, компилятор выдаст ошибку.

Вот пример ограничения использования аннотации@SimpleAnnotation только объявлениями полей:

@Target(ElementType.FIELD)
public @interface SimpleAnnotation {
    // ...
}

Мы можем передать несколько констант, если мы хотим сделать это применимым в большем количестве контекстов:

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PACKAGE })

Мы даже можем сделать аннотацию, чтобы ее нельзя было использовать для комментариев. Это может пригодиться, когда объявленные типы предназначены исключительно для использования в качестве типа элемента в сложных аннотациях:

@Target({})
public @interface NoTargetAnnotation {
    // ...
}

Q7. Что такое мета-аннотации?

Аннотации, которые применяются к другим аннотациям.

Все аннотации, которые не отмечены знаком@Target, или отмечены им, но содержат константуANNOTATION_TYPE, также являются метааннотациями:

@Target(ElementType.ANNOTATION_TYPE)
public @interface SimpleAnnotation {
    // ...
}

Q8. Что такое повторяющиеся аннотации?

Это аннотации, которые можно применять более одного раза к одному и тому же объявлению элемента.

По соображениям совместимости, поскольку эта функция была представлена ​​в Java 8, повторяющиеся аннотации хранятся вcontainer annotation, который автоматически генерируется компилятором Java. Чтобы компилятор сделал это, есть два шага, чтобы объявить их.

Во-первых, нам нужно объявить повторяемую аннотацию:

@Repeatable(Schedules.class)
public @interface Schedule {
    String time() default "morning";
}

Затем мы определяем содержащую аннотацию с обязательным элементомvalue, тип которого должен быть массивом типа повторяющейся аннотации:

public @interface Schedules {
    Schedule[] value();
}

Теперь мы можем использовать @Schedule несколько раз:

@Schedule
@Schedule(time = "afternoon")
@Schedule(time = "night")
void scheduledMethod() {
    // ...
}

Q9. Как вы можете получить аннотации? Как это связано с его политикой хранения?

Вы можете использовать Reflection API или процессор аннотаций для получения аннотаций.

Аннотация@Retention и ее параметрRetentionPolicy влияют на то, как вы можете их получить. В перечисленииRetentionPolicy есть три константы:

  • RetentionPolicy.SOURCE - отменяет аннотацию компилятором, но процессоры аннотации могут их прочитать

  • RetentionPolicy.CLASS - указывает, что аннотация добавлена ​​в файл класса, но недоступна через отражение

  • RetentionPolicy.RUNTIME - аннотации записываются в файл класса компилятором и сохраняются JVM во время выполнения, так что они могут быть прочитаны рефлексивно.

Вот пример кода для создания аннотации, которую можно прочитать во время выполнения:

@Retention(RetentionPolicy.RUNTIME)
public @interface Description {
    String value();
}

Теперь аннотации можно получить с помощью отражения:

Description description
  = AnnotatedClass.class.getAnnotation(Description.class);
System.out.println(description.value());

Обработчик аннотаций может работать сRetentionPolicy.SOURCE, это описано в статьеJava Annotation Processing and Creating a Builder.

RetentionPolicy.CLASS можно использовать, когда вы пишете парсер байт-кода Java.

Q10. Будет ли компилироваться следующий код?

@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.FIELD })
public @interface TestAnnotation {
    int[] value() default {};
}

No. Ошибка времени компиляции, если одна и та же константа перечисления встречается более одного раза в аннотации@Target.

Удаление повторяющейся константы приведет к успешной компиляции кода:

@Target({ ElementType.FIELD, ElementType.TYPE})

Q11. Можно ли расширить аннотации?

No. Аннотации всегда расширяютjava.lang.annotation.Annotation,, как указано вJava Language Specification.

Если мы попытаемся использовать предложениеextends в объявлении аннотации, мы получим ошибку компиляции:

public @interface AnAnnotation extends OtherAnnotation {
    // Compilation error
}

Заключение

В этой статье мы рассмотрели некоторые часто задаваемые вопросы, возникающие в технических интервью для разработчиков Java, касающиеся аннотаций. Это ни в коем случае не исчерпывающий список, и его следует рассматривать только как начало дальнейших исследований.

Мы, например, желаем успехов в любых предстоящих интервью.