Java Annotations Interview Questions (+ Answers) – Java注解的面试问题(+答案)

最后修改: 2017年 4月 30日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

Annotations have been around since Java 5, and nowadays, they are ubiquitous programming constructs that allow enriching the code.

注释从Java 5开始出现,如今,它们是无处不在的编程结构,可以丰富代码的内容。

In this article, we’ll review some of the questions, regarding annotations; that are often asked on technical interviews and, where appropriate; we’ll implement examples to understand their answers better.

在这篇文章中,我们将回顾一些关于注释的问题,这些问题在技术面试中经常被问到,在适当的地方,我们将实施一些例子来更好地理解他们的答案。

2. Questions

2.问题

Q1. What Are Annotations? What Are Their Typical Use Cases?

Q1.什么是注解?它们的典型使用情况是什么?

Annotations are metadata bound to elements of the source code of a program and have no effect on the operation of the code they operate.

注释是绑定在程序源代码元素上的元数据,对其操作的代码没有影响。

Their typical uses cases are:

它们的典型使用情况是。

  • Information for the compiler – with annotations, the compiler can detect errors or suppress warnings
  • Compile-time and deployment-time processing – software tools can process annotations and generate code, configuration files, etc.
  • Runtime processing – annotations can be examined at runtime to customize the behavior of a program

Q2. Describe Some Useful Annotations from the Standard Library.

问题2 描述一下标准库中一些有用的注释

There are several annotations in the java.lang and java.lang.annotation packages, the more common ones include but not limited to:

java.langjava.lang.annotation包中有几个注释,比较常见的注释包括但不限于:。

  • @Override – marks that a method is meant to override an element declared in a superclass. If it fails to override the method correctly, the compiler will issue an error
  • @Deprecated – indicates that element is deprecated and should not be used. The compiler will issue a warning if the program uses a method, class, or field marked with this annotation
  • @SuppressWarnings – tells the compiler to suppress specific warnings. Most commonly used when interfacing with legacy code written before generics appeared
  • @FunctionalInterface – introduced in Java 8, indicates that the type declaration is a functional interface and whose implementation can be provided using a Lambda Expression

Q3. How Can You Create an Annotation?

Q3.你如何创建一个注释?

Annotations are a form of an interface where the keyword interface is preceded by @, and whose body contains annotation type element declarations that look very similar to methods:

注释是接口的一种形式,关键词interface前面有@,,其主体包含annotation type element声明,看起来与方法非常相似。

public @interface SimpleAnnotation {
    String value();

    int[] types();
}

After the annotation is defined, yon can start using it in through your code:

在定义了注解之后,你可以开始在你的代码中使用它。

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

Note that, when providing multiple values for array elements, you must enclose them in brackets.

注意,当为数组元素提供多个值时,必须用括号把它们括起来。

Optionally, default values can be provided as long as they are constant expressions to the compiler:

可以选择提供默认值,只要它们对编译器来说是常量表达。

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

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

Now, you can use the annotation without those elements:

现在,你可以使用没有这些元素的注释。

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

Or only some of them:

或者只是其中的一部分。

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

Q4. What Object Types Can Be Returned from an Annotation Method Declaration?

Q4.注释方法声明可以返回哪些对象类型?

The return type must be a primitive, String, Class, Enum, or an array of one of the previous types. Otherwise, the compiler will throw an error.

返回的类型必须是原始的、StringClassEnum或前述类型之一的数组。否则,编译器将抛出一个错误。

Here’s an example code that successfully follows this principle:

下面是一个成功遵循这一原则的示例代码。

enum Complexity {
    LOW, HIGH
}

public @interface ComplexAnnotation {
    Class<? extends Object> value();

    int[] types();

    Complexity complexity();
}

The next example will fail to compile since Object is not a valid return type:

下一个例子将无法编译,因为Object不是有效的返回类型。

public @interface FailingAnnotation {
    Object complexity();
}

Q5. Which Program Elements Can Be Annotated?

Q5.哪些程序元素可以被注解?

Annotations can be applied in several places throughout the source code. They can be applied to declarations of classes, constructors, and fields:

注释可以在整个源代码的几个地方应用。它们可以应用于类的声明、构造函数和字段。

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

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

Methods and their parameters:

方法和它们的参数。

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

Local variables, including a loop and resource variables:

本地变量,包括一个循环和资源变量。

@SimpleAnnotation
int i = 10;

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

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

Other annotation types:

其他注释类型。

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

And even packages, through the package-info.java file:

甚至还有包,通过package-info.java文件。

@PackageAnnotation
package com.baeldung.interview.annotations;

As of Java 8, they can also be applied to the use of types. For this to work, the annotation must specify an @Target annotation with a value of ElementType.USE:

从 Java 8 开始,它们也可以应用于类型的使用。要做到这一点,注解必须指定一个@Target annotation,其值为ElementType.USE

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

Now, the annotation can be applied to class instance creation:

现在,注解可以被应用于类实例的创建。

new @SimpleAnnotation Apply();

Type casts:

类型铸造。

aString = (@SimpleAnnotation String) something;

Implements clause:

执行条款。

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

And throws clause:

抛出条款。

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

Q6. Is There a Way to Limit the Elements in Which an Annotation Can Be Applied?

Q6.是否有办法限制可以应用注释的元素?

Yes, the @Target annotation can be used for this purpose. If we try to use an annotation in a context where it is not applicable, the compiler will issue an error.

是的,@Target注解可以用于此目的。如果我们试图在一个不适用的上下文中使用注解,编译器会发出一个错误。

Here’s an example to limit the usage of the @SimpleAnnotation annotation to field declarations only:

这里有一个例子,将@SimpleAnnotation注解的使用限制在字段声明中。

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

We can pass multiple constants if we want to make it applicable in more contexts:

如果我们想让它适用于更多的情况,我们可以传递多个常数。

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

We can even make an annotation so it cannot be used to annotate anything. This may come in handy when the declared types are intended solely for use as a member type in complex annotations:

我们甚至可以使一个注解不能被用来注解任何东西。当声明的类型只是为了在复杂的注释中作为成员类型使用时,这可能会很方便。

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

Q7. What Are Meta-Annotations?

Q7.什么是元注解?

Are annotations that apply to other annotations.

是适用于其他注解的注解。

All annotations that aren’t marked with @Target, or are marked with it but include ANNOTATION_TYPE constant are also meta-annotations:

所有没有标注@Target,的注释,或者标注了它但包括ANNOTATION_TYPE常量的注释也是元注释。

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

Q8. What Are Repeating Annotations?

Q8.什么是重复注释?

These are annotations that can be applied more than once to the same element declaration.

这些是可以多次应用于同一元素声明的注释。

For compatibility reasons, since this feature was introduced in Java 8, repeating annotations are stored in a container annotation that is automatically generated by the Java compiler. For the compiler to do this, there are two steps to declared them.

由于兼容性的原因,自从这个功能在Java 8中引入后,重复注解被存储在一个容器注解中,该注解由Java编译器自动生成。为了让编译器做到这一点,有两个步骤来声明它们。

First, we need to declare a repeatable annotation:

首先,我们需要声明一个可重复注解。

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

Then, we define the containing annotation with a mandatory value element, and whose type must be an array of the repeatable annotation type:

然后,我们用一个强制性的value元素来定义包含注释,其类型必须是可重复注释类型的数组。

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

Now, we can use @Schedule multiple times:

现在,我们可以多次使用@Schedule。

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

Q9. How Can You Retrieve Annotations? How Does This Relate to Its Retention Policy?

Q9.你怎样才能检索注释?这与它的保留政策有什么关系?

You can use the Reflection API or an annotation processor to retrieve annotations.

你可以使用Reflection API或注释处理器来检索注释。

The @Retention annotation and its RetentionPolicy parameter affect how you can retrieve them. There are three constants in RetentionPolicy enum:

@Retention 注解及其RetentionPolicy 参数影响你如何检索它们。在RetentionPolicy枚举中有三个常量。

  • RetentionPolicy.SOURCE – makes the annotation to be discarded by the compiler but annotation processors can read them
  • RetentionPolicy.CLASS – indicates that the annotation is added to the class file but not accessible through reflection
  • RetentionPolicy.RUNTIME –Annotations are recorded in the class file by the compiler and retained by the JVM at runtime so that they can be read reflectively

Here’s an example code to create an annotation that can be read at runtime:

下面是一个创建注释的示例代码,可以在运行时读取。

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

Now, annotations can be retrieved through reflection:

现在,注解可以通过反射来检索。

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

An annotation processor can work with RetentionPolicy.SOURCE, this is described in the article Java Annotation Processing and Creating a Builder.

注释处理器可以与RetentionPolicy.SOURCE一起工作,这在Java注释处理和创建生成器一文中有描述。

RetentionPolicy.CLASS is usable when you’re writing a Java bytecode parser.

RetentionPolicy.CLASS在你编写Java字节码分析器时可以使用。

Q10. Will the Following Code Compile?

Q10.以下代码是否可以编译?

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

No. It’s a compile-time error if the same enum constant appears more than once in an @Target annotation.

如果同一个枚举常量在@Target注解中出现一次以上,这就是一个编译时错误。

Removing the duplicate constant will make the code to compile successfully:

移除重复的常量将使代码成功编译。

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

Q11. Is It Possible to Extend Annotations?

Q11.是否有可能扩展注释?

No. Annotations always extend java.lang.annotation.Annotation, as stated in the Java Language Specification.

注释总是扩展java.lang.annotation.Annotation,Java语言规范中所述。

If we try to use the extends clause in an annotation declaration, we’ll get a compilation error:

如果我们试图在注释声明中使用extends子句,我们会得到一个编译错误。

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

3. Conclusion

3.结论

In this article, we covered some of the frequently asked questions appearing in technical interviews for Java developers, regarding annotations. This is by no means an exhaustive list, and should only be considered as the start of further research.

在这篇文章中,我们介绍了一些在Java开发者技术面试中经常出现的关于注解的问题。这决不是一个详尽的清单,只应被视为进一步研究的开始。

We, at Baeldung, wish you success in any upcoming interviews.

我们,在Baeldung,祝你在即将到来的面试中取得成功。

Next »

Top Spring Framework Interview Questions

« Previous

Java Exceptions Interview Questions (+ Answers)