元注解
@Target :标识注解的目标,默认为所有
ElementType.TYPE(用于类)
ElementType.FIELD(用于域,包括enum)
ElementType.METHOD(用于方法)
ElementType.PARAMETER(用于正式参数)
ElementType.CONSTRUCTOR(类型构造方法)
ElementType.LOCAL_VARIABLE(用于本地变量)
ElementType.ANNOTATION_TYPE(用于注解)
ElementType.PACKAGE(用于包)
ElementType.TYPE_PARAMETER(java8,用于输入参数)
ElementType.TYPE_USE (java8,用于类型)
@Retention:注解保留到哪
RetentionPolicy.SOURCE(只保留到源码,编译为.class文件时忽略)
RetentionPolicy.CLASS(只保留到.class文件,运行时忽略,default默认)
RetentionPolicy.RUNTIME(运行时保留,可以通过反射机制读取注解的信息。)
@Documented:将此注解保存在 Javadoc 中
@Inherited:允许子类继承父类的注解
@Repeatable:用于重复使用注解(Java8新增)
常用注解
一、@Override
常用于重写父类的方法,或实现接口的方法,若不满足则报错。
packagejava.lang;import java.lang.annotation.*;/*** 使用在方法上,只存在在源码上*/@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)public @interfaceOverride {
}
二、
@Deprecated
常用于标注一个方法被弃用。
packagejava.lang;import java.lang.annotation.*;import static java.lang.annotation.ElementType.*;/*** 记录JavaDoc,保留至运行时,可使用在构造方法,属性(包括枚举),本地变量,方法,包,公共参数和类*/@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})public @interfaceDeprecated {
}
三、@SuppressWarnings
常用于忽略特定警告,@SuppressWarnings("unchecked", "deprecation")可以同时忽略多个警告。
packagejava.lang;import java.lang.annotation.*;import static java.lang.annotation.ElementType.*;/*** 在类型、域、方法、正是参数、构造方法、本地变量上使用,只存在于源码*/@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)public @interfaceSuppressWarnings {/*** 一般取 unchecked/deprecation,表示忽略 unchecked/deprecation 警告信息*/String[] value();
}
四、@SafeVarargs (Java7)
常用于抑制varargs相关的未检查警告,一般只能用于static、final方法
packagejava.lang;import java.lang.annotation.*;/*** 能记录JavaDoc,保留至运行时,使用在构造方法和方法上*/@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})public @interface SafeVarargs {}
五、@FunctionalInterface (Java8)
编译器检测接口是否符合函数式接口定义
packagejava.lang;import java.lang.annotation.*;/*** 能记录JavaDoc,存在于运行时,只能使用在类上*/@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)public @interface FunctionalInterface {}
自定义注解
首先定义一个注解
packagecom.example.demo.util.annotation;import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inheritedpublic @interfaceMyAnnotation {
String value()default "001";
}
可以看到,在Student的sNo属性上使用了该注解
packagecom.example.demo.util.annotation;importlombok.Data;importlombok.AllArgsConstructor;importlombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructorpublic classStudent {
@MyAnnotationprivateString sNo;privateString sName;
}
处理注解
packagecom.example.demo.util.annotation;importjava.lang.reflect.Field;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.util.Objects;public classAnnotationTest {public static voidmain(String[] args) {//创建一个学号为 002 的学生 kw
Student student = new Student("002", "kw");//获取学生对象对应的类
Class extends Student> clazz =student.getClass();//获取学生类的属性
Field[] declaredFields =clazz.getDeclaredFields();/**循环判断是否存在注解@MyAnnotation
* 若存在则获取该属性的set方法
* 并使用该方法将值改为@MyAnnotation的value值*/@MyAnnotation的valuefor(Field field: declaredFields) {if (field.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation annotation= field.getAnnotation(MyAnnotation.class);if(Objects.nonNull(annotation)) {
String name=field.getName();try{
Method setMethod=clazz.getDeclaredMethod("set" + name.substring(0, 1).toUpperCase() + name.substring(1), String.class);
String annotationValue=annotation.value();
setMethod.invoke(student, annotationValue);
}catch(NoSuchMethodException e) {
e.printStackTrace();
}catch(IllegalAccessException e) {
e.printStackTrace();
}catch(InvocationTargetException e) {
e.printStackTrace();
}
}
}
}//打印
System.out.println(student);
}
}/**输出
Student(sNo=001, sName=kw)*/