1.什么是注解?
注解(Annotation)其实就是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用Annotation,我们开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。
从JDK5.0开始增加了对元数据(MetaData)的支持,也就是注解。
注解可以像修饰符一样被使用,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明,这些信息被保存到注解的"name=value"对中。
2.JDK中的元注解
JDK中的元注解用于其他注解的定义。元注解有:@Retention、@Target、@Documented、@Inherited、@Repeatable五个。
@Retention
Retention为保留维持的意思,@Retention只能用于修饰一个注解的定义,用于指定注解的生命周期,@Retention包括一个RetentionPolicy
类型的成员变量,使用时必须设置值,取值有下面几个:
RetentionPolicy.SOURCE
在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释。RetentionPolicy.CLASS
在class文件中保留(即class保留),当运行Java程序时,JVM不会保留注解。这是默认值RetentionPolicy.RUNTIME
在运行时有效(即运行时保留),当运行Java程序时,JVM会保留注释。程序可以通过反射获取该注释。
@Target
Target目标的意思,@target用于修饰注解的定义,用于指定被修饰的注解能用于修饰哪些程序元素(方法、接口、字段、方法…),取值有以下几个:
-
ElementType.ANNOTATION_TYPE
可以给一个注解进行注解 -
ElementType.CONSTRUCTOR
可以给构造方法进行注解 -
ElementType.FIELD
可以给属性进行注解 -
ElementType.LOCAL_VARIABLE
可以给局部变量进行注解 -
ElementType.METHOD
可以给方法进行注解 -
ElementType.PACKAGE
可以给一个包进行注解 -
ElementType.PARAMETER
可以给一个方法内的参数进行注解 -
ElementType.TYPE
可以给一个类型进行注解,比如类、接口、枚举 -
ElementType.TYPE_PARAMETER
表示该注解可以写在类型变量声明语句中(如泛型声明) -
ElementType.TYPE_USE
:表示该注解可以写在使用类型的任何语句中
后面两个去值为jdk1.8引入
@Documented
Documented为文档的意思,@Documented修饰的注解将被javadoc工具提取成文档。
注意:定义@Documented注解必须设置@Retention的值为
RetentionPolicy.RUNTIME
@Inherited
Inherited为继承的意思,被@Inherited元注解修饰的注解将具有继承性,即如果某个类使用了@Inherited注解,则其子类自动具有该注解。
@Repeatable
Repeatable 是可重复的意思,它是jdk1.8引入得注解,被@Repeatable元注解修饰的注解在同一个地方可以多次使用。
举个例子,一个人他既是程序员又是产品经理,同时他还是个画家:
@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
String role() default "";
}
@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{
}
3.JDK其他内置的注解
JDK中的元注解是为了自定义注解的内置注解,除了元注解还有另外一些内置的注解。
- @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
- @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
- @SuppressWarnings - 指示编译器去忽略注解中声明的警告。
- @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
- @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
4.自定义注解
自定义注解语法
元注解
public @interface 注解名 {成员变量}
-
使用@interface自定义注解时,自动继承了
java.lang.annotation.Annotation
接口 -
自定义注解的成员变量在定义中以无参方法的形式来声明,其方法名和返回值定义了成员的名字和类型,类型只能是
- 八种基本数据类型
- String
- Class 类
- enum 枚举类型
- Annotation 注解类型
- 以上所有类型的数组
-
可以使用
default
关键字指定默认值 -
只有一个参数成员时,建议使用参数名为
value
-
如果定义的注解含有配置参数,那么使用时必须指定参数值
举例:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
public @interface MyAnno {
String value() default "有注解";
}
5.注解与反射
JDK5.0在java.lang.reflect
包下新增了AnnotatedElement
接口,该接口代表程序中可以接受注解的程序元素,我们可以调用AnnotatedElement
对象的方法来获取注解信息
//如果存在该元素的指定类型的注解,则返回这些注解,否则返回 null。
T getAnnotation(Class<T> annotationClass)
//返回此元素上存在的所有注解。
Annotation[] getAnnotations()
//返回直接存在于此元素上的所有注解。
Annotation[] getDeclaredAnnotations()
//如果指定类型的注解存在于此元素上,则返回 true,否则返回 false。
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
举个例子:
一个类的某些字段上被注解标识,在读取该属性时,将注解中的默认值赋给这些属性,没有标记的属性不赋值
自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
public @interface MyAnno {
String value() default "有注解";
}
类:
public class Person {
@MyAnno
private String stra;
private String strb;
private String strc;
public Person(String str1,String str2,String str3){
super();
this.stra = str1;
this.strb = str2;
this.strc = str3;
}
// 省略set get
}
测试
public class MyTest {
public static void main(String[] args) {
Person person = new Person("无注解", "无注解", "无注解");
doAnnoTest(person);
System.out.println(person);
}
public static void doAnnoTest(Object obj){
Class<?> aClass = obj.getClass();
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
if(field.isAnnotationPresent(MyAnno.class)){
MyAnno annotation = field.getAnnotation(MyAnno.class);
if(annotation!=null){
String value = annotation.value();
Method method = null;
try {
method = aClass.getMethod("set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1),String.class);
method.invoke(obj,value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
输出结果:
Person(stra=有注解, strb=无注解, strc=无注解)
参考:
-
https://blog.csdn.net/KKALL1314/article/details/96481557
-
《Java成神之路》