Java annotation注解使用及全面解析

首先Java注解是什么?

注解就是一个标签。通过注解你可以给类or方法or变量添加一个标签。除此之外它没有其他作用了。你所见到的那些关于注解的神奇用法其实都是Java反射和编译器的功劳。

1.元注解

(一切注解的老祖宗:用了给注解贴标签的注解)
- @Documente

表示拥有该注解的元素可通过javadoc此类的工具进行文档化。该类型应用于注解那些影响客户使用带注释(comment)的元素声明的类型。如果类型声明是用Documented来注解的,这种类型的注解被作为被标注的程序成员的公共API。
- @Target

用来约束注解可以应用的地方(如方法、类或字段),其中ElementType是枚举类型,也代表可能的取值范围。请注意,当注解未指定Target值时,则此注解可以用于任何元素之上,多个值使用{}包含并用逗号隔开
- @Retention

用来约束注解的生命周期,分别有三个值,源码级别(source),类文件级别(class)或者运行时级别(runtime)。请注意,当注解未定义Retention值时,默认值是CLASS,如Java内置注解,@Override、@Deprecated、@SuppressWarnning等
- @Inherited

表示该注解类型被自动继承(即:子类能够继承父类的注解)。如果在当前类中查询(通过反射)这个元注解类型并且当前类的声明中不包含这个元注解类型,那么就会自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行直到这个标注类型被找到,或者是查询到顶层的父类。

2.注解的属性

注解中也可以添加属性的。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    int id() default 1;

    String msg();

}

注解属性支持的类型:
- 所有基本类型(int,float,boolean,byte,double,char,long,short)
- String
- Class
- enum
- Annotation

- 上述类型的数组

注解不可以继承
但注解可以嵌套,类似于Java内部类

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {

    @interface Pro {
        String color();
    }

    String name() default "";

}

使用:

@MyTest.Pro(color = "red")
    public int add() {
        return a + b;
}

不过这样做目前没有发现太大的存在意义。因为Pro也只是相当于MyTest注解的一个属性,没有其他特殊功能了。通过反射查找的时候反而要多一层罢了。

3.如何让注解发挥作用

开篇就写了,如果没有反射和编译器的配合的话,注解没有任何特殊效果,它就是个标签。那么是如何让注解发挥作用的呢?
1).反射
Junit单元测试中的各种注解。@Test
最终是通过Junit框架的来发挥@Test的作用的。
2)编译器
比如这个注解,@Deprecated编译器在编译阶段遇到这个注解时会发出提醒警告

4.举个栗子

Mytes.java

//自定义注解
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}

Calculate.java

public class Calculate {

    private int a;
    private int b;

    public Calculate(int a, int b) {
        this.a = a;
        this.b = b;
    }

    //添加注解
    @MyTest
    public int add() {
        return a + b;
    }

    @MyTest
    public int subtract() {
        return a - b;
    }

    @MyTest
    public int multiply() {
        return a * b;
    }

    @MyTest
    public int divide() {
        return a / b;
    }
}

然后写一个测试类Test.java

import java.lang.reflect.Method;

public class Test {

    public static void main(String[] args) {
        Calculate calculate = new Calculate(2, 0);
        Class clazz = calculate.getClass();
        Method[] methods = clazz.getDeclaredMethods();

        int testNum = 0;
        int successNum = 0;
        int errNum = 0;
        for (Method method : methods) {
            testNum++;
            if (method.isAnnotationPresent(MyTest.class)) {
                String methodName = method.getName();
                try {
                    Object ret = method.invoke(calculate);
                    System.out.println("Method:" + methodName + ", Test Success, Result:" + ret);
                    successNum++;
                } catch (Exception e) {
                    String err = "Method:" + methodName + ", Test Failed"
                            + "\n    caused by:" + e.getCause().getClass()
                            + "\n              " + e.getCause().getMessage();
                    System.out.println(err);
                    errNum++;
                }
            }
        }
        System.out.println("MyTest Done. All MyTest:" + testNum + "; SuccessNum:" + successNum + "; ErrNum:" + errNum);
    }
}

5.使用注解的基本套路

//自定义一个color注解
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Color {
    String[] colors();
    int num();
}
Method[] methods = clazz.getDeclaredMethods();
Field field=clazz.getField("age");//借助反射
if (field.isAnnotationPresent(Color.class)){//判断是否使用注解
    Annotation annotation=field.getAnnotation(Color.class);//获取注解
    String[] colors=((Color) annotation).colors();//获取注解某个属性的值
        //接下来就是根据或得到的注解值colors做一些你想做的操作
        //比如colors中包含red,你就咋咋咋
        //比如colors中包含black,你就把它赋值给某个变量

文中代码以上传到github:https://github.com/zhaominso/java-annotation

相关参考:https://blog.csdn.net/briblue/article/details/73824058

猜你喜欢

转载自blog.csdn.net/zhaominpro/article/details/80776011