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,被修饰的方法会被当作一个测试方法。

  • 相关阅读:
    C# 从服务器下载文件
    不能使用联机NuGet 程序包
    NPOI之Excel——合并单元格、设置样式、输入公式
    jquery hover事件中 fadeIn和fadeOut 效果不能及时停止
    UVA 10519 !! Really Strange !!
    UVA 10359 Tiling
    UVA 10940 Throwing cards away II
    UVA 10079 Pizze Cutting
    UVA 763 Fibinary Numbers
    UVA 10229 Modular Fibonacci
  • 原文地址:https://www.cnblogs.com/astropeak/p/6197976.html
Copyright © 2011-2022 走看看