zoukankan      html  css  js  c++  java
  • Annotation: 代码的修饰符

    简介: 是什么, 用途, 为什么有用

    Annotation 是一种元数据(metadata),它本身不是代码,但提供了一些关于代码的数据。这些数据可以是限定代码的一些功能,也可以是增加一些功能。可以将它理解为代码的修饰符,将代码当作一个名词,则Annotation是一个形容词,它使这个名词更加准确、或限定为更小的范围。如红红的苹果,直接说苹果也行,但有了红红的这个形容词,就更加准确了。 Annotation可以向编译器提供一些信息,如检测错误(@Override)、消除编译告警(@SuppressWarning)。 编译期生成代码(@Junit)。运行期提供一些检查机制(@NonNull)。被框架广泛使用。 和comment一样,annotation也能够起到描述代码功能。但它还具有检查机制。 为什么是需要的?有些信息无法通过代码表达出来,此时通过Annotation可以很好的达到。

    使用: 一个简单例子,如@Override。系统提供的annotation,做成列表

    Java 预定义的annotation

    namedescription
    @Deprecated 被修饰的元素已经被弃用,不应该再使用。编译器会打印一个告警,如果这个元素还被使用
    @Override 被修饰元素会覆盖基类的定义。
    @SuppressWarnings 消除一个编译告警。接受一个参数
    @SafeVarargs 指明方法不会对varargs做不安全的操作。unchecked 告警会被抑制
    @FunctionalInterface 被用作为函数式接口,java8引入

    修饰其它annotation的annotation

    @Retention 参数: RetentionPolicy.SOURCE, .CLASS, .RUNTIME. 表示这个annotation 会被保存的地方
    @Documented 元素必须被javadoc文档化
    @Target 参数:ElementType.METHOD, .ANNOTATION_TYPE, .CONSTRUCTOR, .FIELD, .LOCAL_VARIABLE,
      .PACKAGE, .PARAMETER, .TYPE. 指定元素的类型。
    @Inherited 这个annotation会被它修改的类型的子类继承
    @Repeatable 可被多次应用在一个元素上

    REF: https://docs.oracle.com/javase/tutorial/java/annotations/predefined.html

    使用方法,以@Override为例。

    class A {
        void foo(){
            System.out.println("Supper class");
        }
    }
    class A1 extends A {
        @Override
        void foo(){
            System.out.println("Sub class");
        }
    }
    class Test {
        public static void main(String[] args) {
            A a = new A1();
            a.foo();
        }
    }
    

    @Override确保被修饰方法确实是覆盖了一个基类的方法,而不是定义了一个新的方法(这种情况在方法名拼写错误时发生),或重载了一个方法(在参数类型错误时发生)。以下是一个方法名拼写错误的例子。原本想覆盖基类的foo方法,但却拼写错了,导致程序结果错误。通过@Override在编译器就可检测出来。

    class A {
        void foo(){
            System.out.println("Supper class");
        }
    }
    class A1 extends A {
        void fooo(){
            System.out.println("Sub class");
        }
    }
    class Test {
        public static void main(String[] args) {
            A a = new A1();
            a.foo();
        }
    }
    

    定义新的annotation。 涉及到的语法, processor的编写(以及使用APT辅助编写)。

    定义一个新的annotation包括两部分,annotation本身的定义,和 annotation processor的定义。 其中annotation本身的定义相当于给系统增加了一个annotaion类型。 annotation processor是来解析、处理这个annotation. 一个定义annotation的例子:

    定义了一个名为Autocall的annotation,它有一个属性 msg(默认值为"")。@Rentention 说明它会在RUNTIME时使用,@Target说明它只能修饰方法。

    使用这个annotaion,修饰Test的foo方法:

    class Test {
        @Autocall
        public static foo() {
    
        }
        public static void main(String[] args) {
        }
    }
    

    这个annotation设计的作用是使被修饰方法自动被main函数调用。这个需要新增代码来实现,也即为这个annotation编写一个processor来实现。如果没有processor, annotation和comment没什么区别。

    Annotation processor的例子:

    import java.lang.annotation.*;
    import java.lang.Class;
    import java.lang.reflect.Method;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface Autocall {
        String msg() default "";
    }
    
    class AutocallProcessor {
        static void process(Class cls) {
            try{
                Class anntCls= Class.forName("Autocall");
                for(Method mtd: cls.getDeclaredMethods()){
                    Autocall annt = (Autocall)mtd.getDeclaredAnnotation(anntCls);
                    if (annt != null) {
                        // call this Method.
                        try{
                            mtd.invoke(null);
                        } catch(Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            } catch (ClassNotFoundException e){
                System.out.println("ClassNotFoundException");
                System.exit(1);
            }
    
        }
        @Autocall
        static void foo(){
            System.out.println("Foo called");
        }
        public static void main(String[] args) {
            try{
                process(Class.forName("AutocallProcessor"));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
    
            }
        }
    }
    

    在框架中的应用。如Junit中。

    Junit中定义了@Test,被修饰的方法会被当作一个测试方法。

  • 相关阅读:
    du命令、df命令、磁盘分区
    du命令、df命令、磁盘分区
    C#中类和结构体的区别
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    JAVA并查集
    JAVAPrim最小生成树
    自媒体创业怎么起步?如何选择自媒体平台?
    如何在互联网创业?有什么好的技巧?
  • 原文地址:https://www.cnblogs.com/astropeak/p/6197976.html
Copyright © 2011-2022 走看看