深入理解Java:注解(Annotation)自定义注解入门

注解的定义

元注解的源码位置

元注解解析及实例

@Documented

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Dog {
    public String name() default "wangcai";
    public int age() default 0;
}

@Inherited

import java.lang.annotation.Inherited;

@Inherited
public @interface testInherited {
    Sring name();
}

@Target

关键代码

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
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();
}
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
}

@Retention

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
     /**注释将被编译时丢弃*/
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
     /**编译试记录在class文件中,但VM运行时丢弃*/
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
     /**运行时存在,可以通过反射获取*/
    RUNTIME
}

自定义注解

定义标记需要使用元注解

  • 使用元注解@Target来标记该注解的作用范围(空间范围,在哪些地方可以使用)
  • 使用元注解@Retention来标记该注解的作用时间范围(时间范围,在什么时候起作用)
  • 使用元注解@Inherited来标记该注解是否可以由子注解来继承
  • 使用元注解@Documented来标记该注解是否需要自动生成文档
  • 使用@interface关键词来定义注解
  • 在注解内部定义一些相关的属性,一般是方法的形式来定义属性

自定义注解实例

  • 新建自定义注解,这里以idea为例,在想新建注解的位置,鼠标右键->New->Java Class
  • 选择想要的方式,添加名称
    • 选择Annotation,新建一个Food的接口
/**
 * 该注解为一个字段注解
 * Description:
 *
 * @author: jieya
 * Date: 2021-05-19
 * Time: 18:05
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Food {
    String name() default "";
}
  • 选择Class,新建一个
/**
 * 这里定义了食物的相关注解
 * Description:
 *
 * @author: jieya
 * Date: 2021-05-19
 * Time: 18:11
 */
public class FoodAnnotation {

    // 这里是单独定义
//    @Target(ElementType.FIELD)
//    @Retention(RetentionPolicy.RUNTIME)
//    public @interface red {
//    }
//
//    @Target(ElementType.FIELD)
//    @Retention(RetentionPolicy.RUNTIME)
//    public @interface green {
//    }

    // 这里使用枚举类经营定义
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface color {
        /**
         * 颜色枚举
         *
         */
        public enum Color{RED,GREEN};
        /**
         * 颜色属性
         */
        Color color() default color.Color.GREEN;
    }
}
/**
 * 定义了一个食物的实体对象类
 * Description:
 *
 * @author: jieya
 * Date: 2021-05-19
 * Time: 18:34
 */

@Data
@AllArgsConstructor
public class FoodTest {

    @Food
    @FoodAnnotation.color(color = FoodAnnotation.color.Color.GREEN)
    private String bread;

    /**
     * 饮料不算食物,就不加注解
     */
    private String drinks;

    @Food
    @FoodAnnotation.color(color = FoodAnnotation.color.Color.RED)
    private String biscuits;

    /**
     * 以下为使用反射获取注解的内容
     *
     * @param args
     */
    public static void main(String[] args) {
        // 定义一个食物实体对象
        FoodTest food = new FoodTest("桃李面包", "百世", "达利园");
        // 获取类模板
        Class c = food.getClass();
        // 获取所有字段
        for (Field f : c.getDeclaredFields()) {
            // 判断该字段是否有Food注解
            if (f.isAnnotationPresent(Food.class)) {
                Food annotation = f.getAnnotation(Food.class);
                System.out.println("字段:[" + f.getName() + "]," + "该字段使用了Food注解");
                // 判断该字段是否有color注解
                if (f.isAnnotationPresent(FoodAnnotation.color.class)) {
                    FoodAnnotation.color.Color color = f.getAnnotation(FoodAnnotation.color.class).color();
                    System.out.println("字段:[" + f.getName() + "]," + "该字段使用了color注解" + "颜色为" + color);
                }
            } else {
                System.out.println("字段:[" + f.getName() + "]," + "该字段没有使用注解");
            }
        }
    }
}

FIELD注解是最常使用的,其他的注解方法的使用在这里就不在赘述了,都是大同小异的。

05-20 06:24