zoukankan      html  css  js  c++  java
  • Java 注解基本原理

    原文地址

    注解的本质

    「java.lang.annotation.Annotation」接口中有这么一句话,用来描述『注解』。

    The common interface extended by all annotation types
    所有的注解类型都继承自这个普通的接口(Annotation)

    这句话有点抽象,但却说出了注解的本质。我们看一个 JDK 内置注解的定义:

        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.SOURCE)
        public @interface Override {
        }
    

    这是注解 @Override 的定义,其实它本质上就是:

        public interface Override extends Annotation{
            
        }
    

    没错,注解的本质就是一个继承了 Annotation 接口的接口。有关这一点,你可以去反编译任意一个注解类,你会得到结果的。

    一个注解准确意义上来说,只不过是一种特殊的注释而已,如果没有解析它的代码,它可能连注释都不如。

    解析一个类或者方法的注解往往有两种形式,一种是编译期直接的扫描,一种是运行期反射。

    元注解

    『元注解』是用于修饰注解的注解,通常用在注解的定义上。

    JAVA 中有以下几个『元注解』:

    • @Target:注解的作用目标
    • @Retention:注解的生命周期
    • @Documented:注解是否应当被包含在 JavaDoc 文档中
    • @Inherited:是否允许子类继承该注解

    @Target

    @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();
        }
    

    注解接收一个ElementType数组,ElementType是一个枚举,成员如下:

    • ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
    • ElementType.FIELD:允许作用在属性字段上
    • ElementType.METHOD:允许作用在方法上
    • ElementType.PARAMETER:允许作用在方法参数上
    • ElementType.CONSTRUCTOR:允许作用在构造器上
    • ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
    • ElementType.ANNOTATION_TYPE:允许作用在注解上
    • ElementType.PACKAGE:允许作用在包上
    • ElementType.TYPE_PARAMETER:允许作用在类型参数上
    • ElementType.TYPE_USE:允许作用在类型上

    @Retention

    @Retention 用于指明当前注解的生命周期

        @Documented
        @Retention(RetentionPolicy.RUNTIME)
        @Target(ElementType.ANNOTATION_TYPE)
        public @interface Retention {
            /**
             * Returns the retention policy.
             * @return the retention policy
             */
            RetentionPolicy value();
        }
    

    注解接收一个RetentionPolicy数据,RetentionPolicy是个枚举,成员如下:

    • RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件
    • RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件
    • RetentionPolicy.RUNTIME:永久保存,可以反射获取

    JAVA 的内置三大注解

    • @Override
    • @Deprecated 标识类或方法不再推荐使用
    • @SuppressWarnings 主要用来压制 java 的警告

    实现一个自己的注解

    定义一个注解:

        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface HelloAnnotation {
            String value() default "Hello annotation!";
        }
    

    使用这个注解:

        public class UseAnnotation {
        
            @HelloAnnotation
            public void hello() {
                System.out.println("hello");
            }
        
            @HelloAnnotation("Hello world!")
            public void helloWorld() {
                System.out.println("Hello world!");
            }
        }
    

    注解最重要的部分在于对注解的处理。注解处理器就是通过反射机制获取被检查方法上的注解信息,然后根据注解元素的值进行特定的处理。如果没有注解处理器,注解就是个注释,或者连注释都不如。

    处理这个注解:

        public class Test {
        
            public static void main(String[] args) {
                testAnnotation(UseAnnotation.class);
            }
        
            private static void testAnnotation(Class<?> cl) {
                for (Method m : cl.getDeclaredMethods()) {
                    HelloAnnotation ha = m.getAnnotation(HelloAnnotation.class);
                    if (ha != null) {
                        System.out.println("Found My Annotation: " + ha.value());
                    }
                }
            }
        }
    

    输出结果:

        Found My Annotation: Hello annotation!
        Found My Annotation: Hello world!
    

    参考资料

    JAVA 注解的基本原理
    Java注解基本原理

    原文首发在我的简书 [https://www.jianshu.com/p/c342606e255d](https://www.jianshu.com/p/c342606e255d

  • 相关阅读:
    POJ_3104_Drying_(二分,最小化最大值)
    POJ_3273_Monthly_Expense_(二分,最小化最大值)
    POJ_3185_The_Water_Bowls_(反转)
    POJ_2566_Bound_Found_(尺取法+前缀和)
    POJ_3061_Subsequence_(尺取法)
    POJ_3258_River_Hopscotch_[NOIP2015]_(二分,最大化最小值)
    POJ_1064_Cable_master_(二分,假定一个解并判断是否可行)
    POJ_2456_Agressive_cows_(二分,最大化最小值)
    背包九讲之三(多重背包)
    背包九讲之二(完全背包)
  • 原文地址:https://www.cnblogs.com/chaohangz/p/11983144.html
Copyright © 2011-2022 走看看