Java基础16-Java注解简介和最佳实践(一):https://developer.aliyun.com/article/1535695
变量注解
下面是一个变量注解的例子:
public class TheClass { @MyAnnotation(name="someName", value = "Hello World") public String myField = null;}
你可以像这样来访问变量的注解:
Field field = ... //获取方法对象</pre><pre>Annotation[] annotations = field.getDeclaredAnnotations();for(Annotation annotation : annotations){ if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); }}
你可以像这样访问指定的变量注解:
Field field = ...//获取方法对象</pre><pre>Annotation annotation = field.getAnnotation(MyAnnotation.class);if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value());}
Java注解相关面试题
什么是注解?他们的典型用例是什么?
注解是绑定到程序源代码元素的元数据,对运行代码的操作没有影响。
他们的典型用例是:
- 编译器的信息 - 使用注解,编译器可以检测错误或抑制警告
- 编译时和部署时处理 - 软件工具可以处理注解并生成代码,配置文件等。
- 运行时处理 - 可以在运行时检查注解以自定义程序的行为
描述标准库中一些有用的注解。
java.lang和java.lang.annotation包中有几个注解,更常见的包括但不限于此:
- @Override -标记方法是否覆盖超类中声明的元素。如果它无法正确覆盖该方法,编译器将发出错误
- @Deprecated - 表示该元素已弃用且不应使用。如果程序使用标有此批注的方法,类或字段,编译器将发出警告
- @SuppressWarnings - 告诉编译器禁止特定警告。在与泛型出现之前编写的遗留代码接口时最常用的
- @FunctionalInterface - 在Java 8中引入,表明类型声明是一个功能接口,可以使用Lambda Expression提供其实现
可以从注解方法声明返回哪些对象类型?
返回类型必须是基本类型,String,Class,Enum或数组类型之一。否则,编译器将抛出错误。
这是一个成功遵循此原则的示例代码:
enum Complexity { LOW, HIGH}public @interface ComplexAnnotation { Class<? extends Object> value(); int[] types(); Complexity complexity();}
下一个示例将无法编译,因为Object不是有效的返回类型:
public @interface FailingAnnotation { Object complexity();}
哪些程序元素可以注解?
注解可以应用于整个源代码的多个位置。它们可以应用于类,构造函数和字段的声明:
@SimpleAnnotationpublic class Apply { @SimpleAnnotation private String aField; @SimpleAnnotation public Apply() { // ... }}
方法及其参数:
@SimpleAnnotationpublic void aMethod(@SimpleAnnotation String param) { // ...}
局部变量,包括循环和资源变量:
@SimpleAnnotationint i = 10;for (@SimpleAnnotation int j = 0; j < i; j++) { // ...}try (@SimpleAnnotation FileWriter writer = getWriter()) { // ...} catch (Exception ex) { // ...}
其他注解类型:
@SimpleAnnotationpublic @interface ComplexAnnotation { // ...}
甚至包,通过package-info.java文件:
@PackageAnnotationpackage 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 { // ...}
有没有办法限制可以应用注解的元素?
有,@ Target注解可用于此目的。如果我们尝试在不适用的上下文中使用注解,编译器将发出错误。
以下是仅将@SimpleAnnotation批注的用法限制为字段声明的示例:
@Target(ElementType.FIELD)public @interface SimpleAnnotation { // ...}
如果我们想让它适用于更多的上下文,我们可以传递多个常量:
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PACKAGE })
我们甚至可以制作一个注解,因此它不能用于注解任何东西。当声明的类型仅用作复杂注解中的成员类型时,这可能会派上用场:
@Target({})public @interface NoTargetAnnotation { // ...}
什么是元注解?
元注解适用于其他注解的注解。
所有未使用@Target标记或使用它标记但包含ANNOTATION_TYPE常量的注解也是元注解:
@Target(ElementType.ANNOTATION_TYPE)public @interface SimpleAnnotation { // ...}
下面的代码会编译吗?
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.FIELD })public @interface TestAnnotation { int[] value() default {};}
不能。如果在@Target注解中多次出现相同的枚举常量,那么这是一个编译时错误。
删除重复常量将使代码成功编译:
@Target({ ElementType.FIELD, ElementType.TYPE})