一、概述
(一)注解的概述
- Java 注解(Annotation)又称Java标注,是JDK5引入的注释机制。
- Java 语言中的类、构造器、方法、成员变量、参数等都可以以注解的形式标注。
(二)注解的作用
- 对Java中类、方法、变量做标记,然后进行特殊处理。
二、自定义注解
(一)自定义注解格式
public @interface 注解名称 {
public 属性类型 属性名() default 默认值;
}
(二)自定义注解示例
public @interface MyBook {
String id();
String[] names();
double price();
//特殊的属性value,当只定义一个属性且名称为value则调用时可不写value,若有多个,则必须填写
String value();
}
三、元注解
(一)概念: 元注解是以注解的形式作用在注解中的一种注解形式。
(二)常见元注解
- @Target——约束自定义注解的使用范围
- @Retention——声明注解的生命周期
(三)常见元注解参数的常用值
@Target——ElementType枚举类
值 | 作用域 |
TYPE | 类/接口 |
FIELD | 成员变量 |
METHOD | 成员方法 |
PARAMETER | 方法参数 |
CONSTRUCTOR | 构造器 |
LOCAL_VARIABLE | 局部变量 |
@Retention——RententionPolicy枚举类
值 | 作用域 |
SOURCE | 作用于源码阶段,生成的字节码文件不存在 |
CLASS | 作用于源码阶段,字节码文件阶段,运行阶段不存在,默认值 |
RUNTIME | 作用于源码阶段,字节码文件阶段,运行阶段,开发常用 |
(四)使用元注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String value();
}
四、注解解析
(一)概念: 注解解析是判断注解是否存在并解析其内容。
(二)相关API
- Annotation接口:注解的原始接口
- AnnotationElement:定义了注解解析方法
方法 | 说明 |
Annotation[] getDeclaredAnnotations() | 获取当前对象上使用的所有注解,返回注解数组 |
T getDeclaredAnnotation(Class<T> annotationClass) | 根据注解类型获得对应注解对象 |
boolean isAnnotationPresent(Class<Annotation> annotationClass) | 判断对象是否使用了指定接口 |
(三)解析注解的技巧: 注解在哪个成分上,先解析哪个成分对象
(四)解析案例
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String value(); //书名
double price() default 100; //价格 默认为100
String[] authors(); //多位作者
}
@Book(value = "《Java深度学习》",price = 100,authors = {"xxx","xxx","xxx"})
class BookStore{
private String name;
private double price;
private String[] authors;
@Book(value = "《Java浅度学习》",price = 50,authors = {"佚名"})
public void text(){
}
@Override
public String toString() {
return "BookStore{" +
"name='" + name + '\'' +
", price=" + price +
", authors=" + Arrays.toString(authors) +
'}';
}
}
public class AnnotationDemo{
@Test
public void parseClass(){
//1、先得到类对象
Class c = BookStore.class;
//2、判断是否存在
if (c.isAnnotationPresent(Book.class)){
//3、直接获取注解对象
Book annotation = (Book) c.getDeclaredAnnotation(Book.class);
System.out.println(annotation.value());
System.out.println(annotation.price());
System.out.println(Arrays.toString(annotation.authors()));
}
}
@Test
public void parseMethod() throws NoSuchMethodException {
//1、先得到类对象
Method c = BookStore.class.getMethod("text");
//2、判断是否存在
if (c.isAnnotationPresent(Book.class)){
//3、直接获取注解对象
Book annotation = (Book) c.getDeclaredAnnotation(Book.class);
System.out.println(annotation.value());
System.out.println(annotation.price());
System.out.println(Arrays.toString(annotation.authors()));
}
}
}
/*测试结果*/
《Java深度学习》
100.0
[xxx, xxx, xxx]
======================
《Java浅度学习》
50.0
[佚名]
五、注解的应用——模拟Junit测试框架
/*
* 需求:定义若干个方法,只要加了MyTest注解,就可以触发执行
* 分析:获取类中成员方法,判断是否有注解,若有注解则执行,否则不执行
*/
public class JunitDemo {
@MyJunit
public static void test1(){
System.out.println("=======test1========");
}
public static void test2(){
System.out.println("=======test2========");
}
@MyJunit
public static void test3(){
System.out.println("=======test3========");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
Class anno = JunitDemo.class;
Method[] methods = anno.getMethods();
for (Method method :methods) {
if (method.isAnnotationPresent(MyJunit.class)){
method.invoke(anno);
}else System.out.println(method.getName() + "未执行");
}
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyJunit{}