深入理解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注解是最常使用的,其他的注解方法的使用在这里就不在赘述了,都是大同小异的。