• Java Annotation Tutorials


    注:本文主要翻译自Lesson: Annotations,学习一下Java注解。

    Annotations(注解)是一种元数据(metadata),用于描述一段程序但对程序的运行不产生直接影响。

    注解有一些作用,其中包括:

    • 为编译器提供信息——注解可以被编译器用于探测 errors 或者 suppress warnings。
    • 编译时或部署时处理——软件处理注解后可生成代码,XML 文件等。
    • 运行时处理——一些注解可以用于运行时检查。

    Annotations基础

    注解的格式

    注解最简单的格式如下:

    @Entity
    

    @字符告知编译器接下来是一个注解,下面这个例子是一个名为Override的注解:

    @Override
    void mySuperMethod() { ... }
    

    注解还可以包含一些带命名或不带命名的元素,每个元素会有相应的 value:

    @Author(
       name = "Benjamin Franklin",
       date = "3/27/2003"
    )
    class MyClass() { ... }
    

    @SuppressWarnings(value = "unchecked")
    void myMethod() { ... }
    

    如果只包含一个带命名的 value,那么这个 value 的 name 可以忽略:

    @SuppressWarnings("unchecked")
    void myMethod() { ... }
    

    如果注解里没有元素,那么括号可以被省略,参考前面的@Override示例。

    对于同一个声明,可以用多个注解:

    @Author(name = "Jane Doe")
    @EBook
    class MyClass { ... }
    

    如果注解的类型相同,这种情况被称为重复注解(repeating annotation):

    @Author(name = "Jane Doe")
    @Author(name = "John Smith")
    class MyClass { ... }
    

    重复注解自 Java 8 开始支持,详见 Repeating Annotations 部分。

    注解的类型可以是java.langjava.lang.annotation包下面定义的类型,比如前面例子中的OverrideSuppressWarnings就是 Java 预置的注解类型。此外还可以自定义注解类型,如前面例子中的AuthorEbook

    注解可以用在什么地方

    注解可以用于声明类、域、方法和其他程序的元素,当用于声明时,注解往往自成一行。

    从 Java 8 开始,注解还可作为类型(type),如下:

    • 创建类的实例:

      new @Interned MyObject();
      
    • 转型:

      myString = (@NonNull String) str;
      
    • 实现接口:

      class UnmodifiableList<T> implements
          @Readonly List<@Readonly T> { ... }
      
    • 抛异常的声明:

      void monitorTemperature() throws
          @Critical TemperatureException { ... }
      

    这种形式的注解被称为类型注解(type annotation)。

    声明一个注解类型

    在代码中很多注解代替了注释(comments)。

    比如,一个开发团队通常在一个类的 body 起始的位置添加一些重要的注释:

    public class Generation3List extends Generation2List {
    
       // Author: John Doe
       // Date: 3/17/2002
       // Current revision: 6
       // Last modified: 4/12/2004
       // By: Jane Doe
       // Reviewers: Alice, Bill, Cindy
    
       // class code goes here
    
    }
    

    如果使用注解的话,首先要定义一个注解类型,语法如下:

    @interface ClassPreamble {
       String author();
       String date();
       int currentRevision() default 1;
       String lastModified() default "N/A";
       String lastModifiedBy() default "N/A";
       // Note use of array
       String[] reviewers();
    }
    

    注解的定义和接口的定义有些像,interface前面多了个@

    上面这个注解的定义中包括了注解类型和元素声明,其中 default 值是可选的。

    定义好注解之后,我们可以像下面这样使用它:

    @ClassPreamble (
       author = "John Doe",
       date = "3/17/2002",
       currentRevision = 6,
       lastModified = "4/12/2004",
       lastModifiedBy = "Jane Doe",
       // Note array notation
       reviewers = {"Alice", "Bob", "Cindy"}
    )
    public class Generation3List extends Generation2List {
    
    // class code goes here
    
    }
    

    Note:为了让 Java Doc 包含注解@ClassPreamble的信息,我们需要在定义@ClassPreamble时为它再加上注解@Documented

    // import this to use @Documented
    import java.lang.annotation.*;
    

    @Documented
    @interface ClassPreamble {

    // Annotation element definitions

    }

    预置的注解类型

    Java API 中预定义了一些注解类型,一些用于编译器,还有一些用于其它注解。

    Java使用的注解类型

    java.lang中预置的注解有:@Deprecated, @Override, 和 @SuppressWarnings

    @Deprecated注解表示被标记的元素是deprecated的,不建议再使用的元素。当程序使用了被@Deprecated注解的方法、类或域时,编译器会生成一个warning信息。当一个元素是deprecated,在Javadoc中也要使用@deprecated标记,Doc中的d小写,注解中是大写的D

     // Javadoc comment follows
        /**
         * @deprecated
         * explanation of why it was deprecated
         */
        @Deprecated
        static void deprecatedMethod() { }
    }
    
    

    @Override注解告诉编译器,该方法是重写自父类的方法:

    // mark method as a superclass method
       // that has been overridden
       @Override 
       int overriddenMethod() { }
    

    @Override的好处是如果这个方法没用正确重写父类的方法时,编译器会产生一个 error 提示。

    @SuppressWarnings注解提示编译器不用产生指定的 warning 信息,如调用一个 deprecated 方法时,编译器会生成一个 waring 提示,使用@SuppressWarnings注解后,这个 waring 就被抑制了:

    // use a deprecated method and tell 
       // compiler not to generate a warning
       @SuppressWarnings("deprecation")
        void useDeprecatedMethod() {
            // deprecation warning
            // - suppressed
            objectOne.deprecatedMethod();
        }
    

    @SafeVarargs用于方法或构造器时,断言可变参数不会产生潜在的危险,由可变参数使用而产生的 warning 会被 suppressed。

    @FunctionalInterface是Java 8引入的,表示函数式接口。

    注解的注解

    用于其它注解的注解,被称为元注解(meta-annotations),下面设计java.lang.annotation包里的相关注解。

    @Retention指定了注解的保留方式:

    • RetentionPolicy.SOURCE – 被标记的注解只保留在源码级别,会被编译器忽略。
    • RetentionPolicy.CLASS – 被标记的注解保留至编译时,会被JVM忽略。
    • RetentionPolicy.RUNTIME – 被标记的注解被JVM保留,会用于运行时环境。

    @Documented注解信息会被 Javadoc 工具写入文档。

    @Target起限制作用,表示注解用于描述哪种 Java 元素:

    • ElementType.ANNOTATION_TYPE 用于描述注解
    • ElementType.CONSTRUCTOR 用于描述构造器
    • ElementType.FIELD 用于描述域
    • ElementType.LOCAL_VARIABLE 用于描述局部变量
    • ElementType.METHOD 用于描述方法的注解
    • ElementType.PACKAGE 用于描述包
    • ElementType.PARAMETER 用于描述参数
    • ElementType.TYPE 用于描述一个类的任何元素

    @Inherited表示该注解是可以被继承的,只能用于声明类。

    @Repeatable在Java 8引入,表示被标记的注解可以被重复用于同一个声明。


    扩展阅读:

  • 相关阅读:
    力扣(LeetCode)605. 种花问题
    力扣(LeetCode)463. 岛屿的周长
    力扣(LeetCode)561. 数组拆分 I
    力扣(LeetCode) 263. 丑数
    区块链历史
    力扣(LeetCode) 821. 字符的最短距离
    力扣(LeetCode)804. 唯一摩尔斯密码词
    cmd 查看端口
    nginx windows版 下载和启动
    luogu P1270 “访问”美术馆
  • 原文地址:https://www.cnblogs.com/kodyan/p/5442648.html
Copyright © 2020-2023  润新知