Java 注解

作者: numqin | 来源:发表于2018-08-16 16:14 被阅读7次

    概念

    在 Java 计算机编程语言中,注解是一种可以添加到 Java 源代码的元数据。

    元数据是提供有关其他数据信息的数据。也可以理解为与数据有关的数据。

    更通俗的来说就是:将数据与程序元素(类、方法、成员变量等)关联。

    为什么要引入注解

    在使用 Annotation(注解)之前,XML 被广泛应用于描述元数据。但 XML 在某些方面上会给维护带来麻烦。比如我为某些类声明些数据,随着类的增加,XML 维护难度也随着增加。所以 Annotation 这种与代码关联更紧密的方式诞生了。

    XML 和 Annotation 各有优缺点。在定义全局的配置时像 XML 这种统一管理的方式将会更好,而在进行些方法、属性、类的声明的时候 Annotation 会更易于维护。

    所以许多框架是将 XML 和 Annotation 两种方式结合使用。

    注解的应用

    • 编译检查
    • 反射中使用 Annotation
    • 帮助生成帮助文档
    • 通过注解生成文件

    自定义注解

    定义注解

    注解通过 @interface 关键字进行定义

    public @interface Testable {
        
    }
    

    使用注解:可以写在类上,方法上,参数上……..

    @Testable
    public class Test {
    
        @Testable
        private int test;
    
        @Testable
        public Test(@Testable int test) {
            this.test = test;
        }
    
        @Testable
        public void foo() {
            @Testable
            int b;
        }
    }
    

    注解属性

    注解中还可以声明属性

    public @interface Testable {
        String value();
    }
    

    如果注解中只有一个熟悉可以直接命名为 value ,使用时无需再声明属性名

    @Testable("Test")
    public void TestClass() {
    }
    

    如果有多个值。

    public @interface Person {
        String name() default "qinlei";
        int age();
    }
    

    可以通过 属性名声明

    @Person(name = "qinlei1", age = 15)
    public class Test {
    }
    

    如果有默认值得可以不声明,默认会使用默认值

    @Person(age = 5)
    public class Test {
    }
    

    元注解

    Java 5.0 在 Java.lang.annotation 提供了四种元注解,专门用于注解其他的注解:

    @Documented

    一个简单的 Annotations 标记注释,表示是否将注解信息添加到 Java 文档中。

    @Retention

    定义注解的有效范围;有三个值可以设置

    RetentionPolicy.SOURCE:在源码阶段保留,编译时就不在有任何意义,不会写入字节码文件,像@Override,@SuppressWarnings 都属于这类注解。

    RetentionPolicy.CLASS:在类加载时候丢失。在字节码文件的处理中有用。注解默认使用该方式。

    RetentionPolicy.RUNTIME:始终有用,在代码运行时依然有效。可以通过反射获取注解信息。

    @Target

    表示注解可以给什么程序元素注解。@Target 可设置的值如下,可设置多个:

    • ElementType.TYPE:可用于定义类、接口、enum
    • ElementType.FIELD:可用于定义全局变量
    • ElementType.METHOD:可用于定义方法
    • ElementType.PARAMETER:可用于定义参数
    • ElementType.CONSTRUCTOR:可用于定义构造器
    • ElementType.LOCAL_VARIABLE:可用于定义局部变量
    • ElementType.ANNOTATION_TYPE:可用于定义注解
    • ElementType.PACKAGE:用于记录java文件的package信息

    @Inherited

    Inherited 是可继承的意思。举个例子

    定义一个带 @Inherited 的注解

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    public @interface Test {
    }
    
    @Test
    class Parent {
    }
    
    class Child extends Parent {
        public static void main(String[] args) {
          //输出Child是否有被 @Test 注解,最后的输出为 true, 如果去掉 Test 中的 @Inherited 输出为 false
          System.out.println(Child.class.isAnnotationPresent(Test.class));
        }
    }
    

    上面的例子中 Child 类很明显是没有被 @Test 注解的,但由于Child 继承了 Parent。而 Parent 的注解里含有 @Inherited,所以 Child 也可以获取到 @Test

    Java 常见注解

    @Override

    定义如下:

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

    这个大家应该熟悉,主要是用于检查我们是否覆盖了父类方法时使用,用于检测是否方法名是否写错了,写错了会编辑器会提示出来。

    @Deprecated

    定义如下:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
    

    这个是将方法、构造器、成员变量等标记为过时,即不建议使用了。编辑器会有提示如下:(看 info 有删除线)

    image-20180816153542908

    @SuppressWarnings

    定义如下:

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

    该注解用于告诉编辑器我们忽略那些警告像下面的 new ArrayList(); 有一个黄色的背景。我们只要加上 @SuppressWarnings("unchecked") 那黄色背景就被我们忽略了。

    image-20180816153753890 image-20180816153923386

    �@SafeVarargs

    定义如下:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
    public @interface SafeVarargs {}
    

    参数安全类型注解。它的目的是提醒开发者不要用参数做一些不安全的操作,它的存在会阻止编译器产生 unchecked 这样的警告。它是在 Java 1.7 的版本中加入的。

    @FunctionalInterface

    定义如下:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface FunctionalInterface {}
    

    约束 interface 只能有一个普通方法

    image-20180816155147172

    静态方法和默认方法除外

    image-20180816155348931

    @Repeatable

    定义如下:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Retention {
        RetentionPolicy value();
    }
    

    @Repeatable 表明可重复定义注解,例子如下:

    FkTag 是我们需要使用的注解,FkTags 相当于 FkTag 的容器,关键看第三段代码。

    @Repeatable(FkTags.class)
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface FkTag {
        String name() default "qinlei";
    
        int age();
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface FkTags {
        FkTag[] value();
    }
    
    //@FkTags({@FkTag(age = 5), @FkTag(age = 6)}) 下面是这一句的简化写法
    @FkTag(age = 5)
    @FkTag(name = "qinlei1", age = 15)
    public class FkTagTest {
    }
    

    最后附上一张图

    图非本人画的

    img 微信公众号

    参考

    https://blog.csdn.net/briblue/article/details/73824058

    https://en.wikipedia.org/wiki/Java_annotation

    http://www.cnblogs.com/skywang12345/p/3344137.html

    https://www.cnblogs.com/mandroid/archive/2011/07/18/2109829.html

    http://www.importnew.com/10294.html

    http://www.cnblogs.com/doit8791/p/4886567.html

    https://segmentfault.com/q/1010000000476689

    相关文章

      网友评论

        本文标题:Java 注解

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