Java – Annotation 注解的使用
简介
Java 1.5 版本推出的一种用于提示JVM注释的方式,注解。
Annotation 注解的声明
注解声明使用固定格式:
public @interface MyAnno { }
注解中可以自定义变量,其中有以下几个规则:
1.变量名为 value 时,且似需赋值给 value 时,注解的使用时,可以省略定义 value 变量名。
2.当变量是一种类型的数组时,如果数组中的成员数只有一个时,可以省略【 {} 】符
public @interface MyAnno {
/**
* 定义一个名为 value 的变量
* 使用这个变量时,如果仅使用value变量,则可以省略赋值的变量名
* @return
*/
String value() default "hello";
String[] name() default "unsoft";
}
在使用这个注解时,可以这样使用:
@MyAnno("hello")
public class MyAnnoDemo { }
但是如果需要赋值多个值时,则 value 不能省略
@MyAnno(value = "hello",name = "unsoft")
public class MyAnnoDemo { }
如果变量是一个数组,当数组成员只有一个的时候,可以省略【 {} 】 号,如:
// name 定义的是一个 String[] 数组,当name 只有一个成员时,可以不用定义成 {"unsoft"}
@MyAnno(value = "hello",name = "unsoft")
public class MyAnnoDemo { }
但是当如果赋值多个数据给数组时,则【 {} 】不能省略:
// name 定义的是一个 String[] 数组,当name 只有两个以上成员时,则不可以省略 { }
@MyAnno(value = "hello",name = {"unsoft","tzming"})
public class MyAnnoDemo { }
元注解
元注解指的是,在注解上面声明的注解,元注解有两个分别是:
@Target
@Target 是用于声明定义这个注解的使用范围,我们知道,注解可以用在【类】、【方法】、【成员变量】、【形参】等等的地方,那么可以通过加上 @Target 来规定我们自己定义的注解只允许用在什么地方。默认全部地方都可以用
public enum ElementType {
/** Class, interface (including annotation interface), enum, or record
* declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation interface declaration (Formerly known as an annotation type.) */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE,
/**
* Module declaration.
*
* @since 9
*/
MODULE,
/**
* Record component
*
* @jls 8.10.3 Record Members
* @jls 9.7.4 Where Annotations May Appear
*
* @since 16
*/
RECORD_COMPONENT;
}
@Retention
@Retention 是定义声明这个注解的可用阶段,有三种阶段,分别是【代码阶段】、【字节码文件阶段】、【运行时阶段】
若定义了【代码阶段】后,代码在编译后,这个注解就不会存在。通常开发的时候,都使用【运行阶段】
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,
/**
* 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(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
}
步骤二:创建一个使用注解的类
public class MyAnnoDemo {
@MyAnno
public void method1(){
System.out.println("方法一被执行");
}
public void method2(){
System.out.println("方法二被执行");
}
@MyAnno
public void method3(){
System.out.println("方法三被执行");
}
}
步骤三:通过反射,判断该类中有那些方法是使用了对应的注解。如果有,则执行该方法
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 使用反射取得该类名的控制
Class<?> clazz = MyAnnoDemo.class;
// 取得该类的构造方法
Constructor<?> constructor = clazz.getConstructor();
// 实例化一个对象
MyAnnoDemo obj = (MyAnnoDemo) constructor.newInstance();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
// 设置强行反射控制
method.setAccessible(true);
// 如果该方法中存在 MyAnno 注解的话
if (method.isAnnotationPresent(MyAnno.class)){
// 就执行该方法
method.invoke(obj);
}
}
}
}
共有 0 条评论