Java 注解工作原理

Posted by ChenJY on August 30, 2017 | Viewed times

什么是注解

注解也叫 元数据,为方便在代码中添加信息提供的一种形式化方法。它们可以提供用来完整描述程序所需的信息,而这些信息无法用 Java 来表达,因此注解使得我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息。注解同样还有利于代码阅读和编译器类型检查等。Java SE5 内置了三种,定义在 java.lang 中的注解:

  1. @Override:表示当前的方法定义将覆盖超类中的方法,如果方法签名对应不正确,编译器会发出错误提示。
  2. @Deprecated:如果使用注解为它的元素,编译器会发出错误提示。
  3. @SuppressWarnings:抑制编译器警告,或者是关闭不当的编译器警告信息。

Java 还提供另外四种注解用于创建新注解。

定义注解

定义注解时,会需要一些元注解(meta-annotation)的帮助,例如 @Target@Retention。 @Target 用来定义你的主解将被用在什么地方,@Retention 定义注解在哪个级别可用,在源代码(SOURCE)中、类文件(CLASS) 亦或者运行时(RUNTIME):

@Target(ElementType.METHOD)  //指作用在一个方法上
@Retention(RetentionPolicy.RUNTIME) //指作用在运行时
public @interface Test {}

写一个自定义注解

创建自定义注解和创建一个接口相似,但是注解的 interface 关键字需要以 @ 符号开头。

自定义注解

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
    public @interface MethodInfo{
    String author() default 'Pankaj';
    String date();
    int revision() default 1;
    String comments();
}

使用自定义注解

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

public class AnnotationExample {

public static void main(String[] args) {

    @Override
    @MethodInfo(author = 'Pankaj', comments = 'Main method', date = 'Nov 17 2012', revision = 1)
    public String toString() {
        return 'Overriden toString method';
    }

    @Deprecated
    @MethodInfo(comments = 'deprecated method', date = 'Nov 17 2012')
    public static void oldMethod() {
        System.out.println("old method, don't use it.");
    }

    @SuppressWarnings({ 'unchecked', 'deprecation' })
    @MethodInfo(author = 'Pankaj', comments = 'Main method', date = 'Nov 17 2012', revision = 10)
    public static void genericsTest() throws FileNotFoundException {
        List l = new ArrayList();
        l.add('abc');
        oldMethod();
    }
}

利用反射解析自定义注解

注解的 RetentionPolicy 应该设置为 RUNTIME 否则 java 类的注解信息在执行过程中将不可用,那么我们也不能从中得到任何和注解有关的数据。

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class AnnotationParsing {

public static void main(String[] args) {
    try {
    for (Method method : AnnotationParsing.class
        .getClassLoader()
        .loadClass(('com.journaldev.annotations.AnnotationExample'))
        .getMethods()) {
        // checks if MethodInfo annotation is present for the method
        if (method.isAnnotationPresent(com.journaldev.annotations.MethodInfo.class)) {
            try {
        // iterates all the annotations available in the method
                for (Annotation anno : method.getDeclaredAnnotations()) {
                    System.out.println('Annotation in Method ''+ method + '' : ' + anno);
                    }
                MethodInfo methodAnno = method.getAnnotation(MethodInfo.class);
                if (methodAnno.revision() == 1) {
                    System.out.println('Method with revision no 1 = '+ method);
                    }

            } catch (Throwable ex) {
                    ex.printStackTrace();
                    }
        }
    }
    } catch (SecurityException | ClassNotFoundException e) {
            e.printStackTrace();
         }
    }

}

参考资料

许可协议


0

Comment