自定义注解的使用
前言
一、注解是什么?
注解也叫元数据,例如我们常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解
一般常用的注解可以分为三类:
一类是Java自带的标准注解,包括@Override(标明重写某个方法)、@Deprecated(标明某个类或方法过时)和@SuppressWarnings(标明要忽略的警告),使用这些注解后编译器就会进行检查。
一类为元注解,元注解是用于定义注解的注解,包括@Retention(标明注解被保留的阶段)、@Target(标明注解使用的范围)、@Inherited(标明注解可继承)、@Documented(标明是否生成javadoc文档)
一类为自定义注解,可以根据自己的需求定义注解
二、四个元注解
学习自定义注解之前,必须要对四个元注解有所了解,一般情况下,大部分注解都是由这四个元注解衍生的。
@Retention
用于定义注解的生命周期,值只有三个类型
public enum RetentionPolicy {
SOURCE,//源码级别
CLASS,//编译器级别
RUNTIME//运行器级别
}
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
由上述源码,可见,该注解能接收的值是单个,且已有的常量值仅有三个级别。
@Target
用于定义注解修饰的目标,指定了目标后,自定义的注解就可以声明在目标上。
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
由上述源码,可见,该注解可以接收的值是一个数组,因此可以接收多个常量值,已有的常量值定义在ElementType中。例如接收的TYPE和FIELD,就说明该注解声明的注解,能使用在类和字段上。
@Inherited
为注解提供自动继承的功能,如@Transactional,
类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解
@Documented
使用@Documented标注了,在生成javadoc的时候就会把@Documented注解给显示出来。只是用来做标识,没什么实际作用,了解就好。
三、自定义注解示例
创建自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Name {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sex {
//限制性别,只有男女
enum GenderType{
Male("男"),
Female("女");
private String genderStr;
GenderType(String arg0){
this.genderStr = arg0;
}
@Override
public String toString() {
return genderStr;
}
}
GenderType gender() default GenderType.Male;
}
使用注解:
public class Person {
@Name(value = "junjie")
public String name;
@Sex(gender = Sex.GenderType.Male)
public String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
使用反射解析:
public class AnnotionUtils {
public static Person getBean(Class<?> cs){
Person person = new Person();
Field[] declaredFields = cs.getDeclaredFields();
for (Field field : declaredFields){
if (field.isAnnotationPresent(Name.class)){
Name annotation = field.getAnnotation(Name.class);
String value = annotation.value();
person.setName(value);
}
if (field.isAnnotationPresent(Sex.class)){
Sex annotation = field.getAnnotation(Sex.class);
String value = annotation.gender().toString();
person.setSex(value);
}
}
return person;
}
public static void main(String[] args) {
Person bean = getBean(Person.class);
System.out.println(bean);
}
}
测试后的运行结果:
Person{name=‘junjie’, sex=‘男’}
四、注解类可声明的类型
参考:
https://blog.csdn.net/weixin_45784642/article/details/103171244
自定义注解中可以包含的类型:8种基本数据类型,String,Class,enum类型,注解类型,以及由以上类型组成的数组,例如:
public @interface test{
//申明枚举
enum Status {z1,z2,z3};
//布尔类型申明
boolean isbool() default true;
//字符串申明
String b1() default "0";
//枚举类型
Status status() default Status.z1;
String[] reportedBy();
}