大厂最新Java注解面试问题

1.简介

自Java 5以来,注释已经出现,而现在,它们是无处不在的编程结构,可以丰富代码。

在本文中,我们将回顾一些关于注释的问题; 通常会在技术面谈时询问,并在适当情况下; 我们将实施示例以更好地理解他们的答案。

2.问题

Q1。什么是注释?他们的典型用例是什么?

注释是绑定到程序源代码元素的元数据,对它们运行的​​代码的操作没有影响。

他们的典型用例是:

  • 编译器的信息 - 使用注释,编译器可以检测错误或抑制警告
  • 编译时和部署时处理 - 软件工具可以处理注释并生成代码,配置文件等。
  • 运行时处理 - 可以在运行时检查注释以自定义程序的行为

Q2。从标准库中描述一些有用的注释。

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

  • @Override -标记方法是否覆盖超类中声明的元素。如果它无法正确覆盖该方法,编译器将发出错误
  • @Deprecated - 表示该元素已弃用且不应使用。如果程序使用标有此批注的方法,类或字段,编译器将发出警告
  • @SuppressWarnings - 告诉编译器禁止特定警告。在与泛型出现之前编写的遗留代码接口时最常用的
  • @FunctionalInterface - 在Java 8中引入,表明类型声明是一个功能接口,可以使用Lambda Expression提供其实现

Q3。你怎么能创建一个注释?

注释是一种接口形式,其中关键字接口@开头,其主体包含与方法非常相似的注释类型元素声明:



public @interface SimpleAnnotation {

    String value();



    int[] types();

}
 

 

定义注释后,yon可以通过代码开始使用它:

@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。可以从注释方法声明返回哪些对象类型?

返回类型必须是基本类型,StringClassEnum或以前类型之一的数组。否则,编译器将抛出错误。

这是一个成功遵循这个原则的示例代码:

enum Complexity {

    LOW, HIGH

}



public @interface ComplexAnnotation {

    Class<? extends Object> 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.baeldung.interview.annotations;

从Java 8开始,它们也可以应用于类型的使用。为此,注释必须指定值为ElementType.USE@Target注释:

@Target(ElementType.TYPE_USE)

public @interface SimpleAnnotation {

    // ...

}

现在,注释可以应用于类实例创建:

new @SimpleAnnotation Apply();

类型转换:

aString = (@SimpleAnnotation String) something;

实施条款:

public class SimpleList<T>

  implements @SimpleAnnotation List<@SimpleAnnotation T> {

    // ...

}

抛出条款:

	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中引入的,因此重复注释存储在由Java编译器自动生成的容器注释中。对于编译器来说,执行此操作有两个步骤来声明它们。

首先,我们需要声明一个可重复的注释:

@Repeatable(Schedules.class)

public @interface Schedule {

    String time() default "morning";

}

然后,我们使用强制元素定义包含注释,其类型必须是可重复注释类型的数组:

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 -Annotations由编译器记录在类文件中,并由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和Creating a Builder一文中有所描述。

当您编写Java字节码解析器时,RetentionPolicy.CLASS可用。

Q10。下面的代码会编译吗?

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

public @interface TestAnnotation {

    int[] value() default {};

}

不。如果在@Target注释中多次出现相同的枚举常量,那么这是一个编译时错误。

删除重复常量将使代码成功编译:

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

Q11。是否可以扩展注释?

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

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

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

结论

在本文中,我们介绍了Java开发人员关于注释的技术访谈中出现的一些常见问题。这绝不是一份详尽的清单,只应被视为进一步研究的开始。

在Baeldung,我们祝愿您在即将进行的任何采访中取得成功。

下一个»

顶级Spring框架面试问题

翻译自  baeldung的文章

地址:https://www.baeldung.com/java-annotations-interview-questions

 

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐