美文网首页
java注解 最接地气的一篇

java注解 最接地气的一篇

作者: remax1 | 来源:发表于2020-05-28 11:28 被阅读0次

    前言

    官方定义:
    Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。

    这也太官话了,听不懂。。。假设代码有生命的话,注解就是代码的标签。举个例子,人也会被打标签,比如帅哥就是我的标签。注解就是代码的标签。

    既然注解是标签,如何给代码打标签呢,别急,让我们先从注解的注解来讲起,即java的元注解。
    注解的注解,翻译一下就是注解的标签。

    元注解

    元注解有 @Retention、@Target、@Inherited、@Repeatable、 @Documented5 种。

    @Retention

    当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。

    ① RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
    ② RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
    ③ RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

    再浅显点,第一种就是java文件的时候有效,第二种就是java文件编译成class文件时一直有效,第三种就是class文件加入到虚拟机时,一直有效。

    //活得最久的注解
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Test {
    }
    

    @Target

    这个标签指定了注解运用的地方,当一个注解被@Target注解时,这个注解就被限定了运用的场景。

    ElementType.ANNOTATION_TYPE 可以给一个注解进行注解 ElementType.CONSTRUCTOR 可以给构造方法进行注解
    ElementType.FIELD 可以给属性进行注解 ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
    ElementType.METHOD 可以给方法进行注解 ElementType.PACKAGE 可以给一个包进行注解
    ElementType.PARAMETER 可以给一个方法内的参数进行注解 ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

    //只能用在方法上
    @Target(ElementType.METHOD)
    //活得最久的注解
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Test {
    }
    

    @Inherited

    一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。

    举个例子,父亲被打上了富豪的标签,那他儿子就是富二代。这就是@Inherited的作用。

    @Repeatable

    @Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。什么样的注解会多次应用呢?通常是注解的值可以同时取多个。比如一个男人既是丈夫又是孩子,有多个标签。

    @Documented

    它的作用是能够将注解中的元素包含到 Javadoc 中去。

    注解的属性

    注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。

    //只能用在方法上
    @Target(ElementType.METHOD)
    //活得最久的注解
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Test {
        String name();
        int age();
    }
    

    测试类:

    public class TestAnnotation {
        @Test(name = "小沈阳",age = 30)
        void test(){
        }
    }
    

    需要注意的是,在注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组。

    注解的提取

    我给代码打了标签,怎么去获取它,获取了之后又要拿来做什么?
    注解通过反射获取。

    public class TestAnnotation {
        @Test(name = "小沈阳",age = 30)
        public void todo(){
                try {
                    Method method = TestAnnotation.class.getMethod("todo");
                    //是否应用了注解
                    if (method.isAnnotationPresent(Test.class)) {
                        Test annotation = method.getAnnotation(Test.class);
                        System.out.println("name: " + annotation.name());
                        System.out.println("age: " + annotation.age());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
    
        public static void main(String[] args) {
            TestAnnotation annotation= new TestAnnotation();
            annotation.todo();
        }
    }
    

    首先通过反射获取method,在判断在这个方法种是否用到了注解,用到了之后再去获取注解的值。
    运行结果:

    name: 小沈阳
    age: 30
    

    上面只是举了个作用在方法上面的注解提取。类,属性都可以提取注解,不过还是得借助于反射。

    注解的使用场景

    再次回到官方文档上来:
    注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。
    注解有许多用处,主要如下:
    提供信息给编译器: 编译器可以利用注解来探测错误和警告信息 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、
    Html文档或者做其它相应处理。
    运行时的处理: 某些注解可以在程序运行的时候接受代码的提取 值得注意的是,注解不是代码本身的一部分。

    当开发者使用了Annotation 修饰了类、方法、Field 等成员之后,这些 Annotation 不会自己生效,必须由开发者提供相应的代码来提取并处理 Annotation 信息。这些处理提取和处理 Annotation 的代码统称为 APT(Annotation Processing Tool)。

    所以注解是给编译器用的或者APT用的,比如ButterKnife,再比如Retrofit的注解,具体的实现就不具体说了,感兴趣可以去看看开源框架的源码。

    关于java预置的注解

    @Deprecated

    这个元素是用来标记过时的元素。编译器在编译阶段遇到这个注解时会发出提醒警告,告诉开发者正在调用一个过时的元素比如过时的方法、过时的类、过时的成员变量。

    @Documented
    //活得最久
    @Retention(RetentionPolicy.RUNTIME)
    //作用范围贼广
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
    

    看到这些是不是貌似都很熟悉呢。

    @Override

    子类要复写父类中被 @Override 修饰的方法

    //作用范围在方法中
    @Target(ElementType.METHOD)
    //只在java文件中有效,命短
    @Retention(RetentionPolicy.SOURCE)
    public @interface Override {
    }
    

    @SuppressWarnings

    阻止警告的意思。之前说过调用被 @Deprecated 注解的方法后,编译器会警告提醒,而有时候开发者会忽略这种警告,他们可以在调用的地方通过 @SuppressWarnings 达到目的。

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings { 
        String[] value();
    }
    

    总结

    注解的提取需要借助java的反射技术,反射比较耗资源,而且会跳过安全检查。Apt技术要慎用。。

    相关文章

      网友评论

          本文标题:java注解 最接地气的一篇

          本文链接:https://www.haomeiwen.com/subject/iwloahtx.html