• 09_Java注解


    本章章节

    > 9.1 注解(Annotation)

    > 9.2 JDK提供的几个基本注解

    > 9.3 自定义注解

    9.1 注解(Annotation)简介

      Annotation(注解) JDK1.5之后增加的一个新特性,这种特性被称为元数据特性,在JDK1.5之后称为注解。注解使得Java源代码中不但可以包含功能性的实现代码,还可以添加元数据。注解的功能类似于代码中的注释,它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释。所不同的是注解不是提供代码功能的说明,而是实现程序功能的重要组成部分。Java注解已经在很多框架中得到了广泛的使用,用来简化程序中的配置。代码分析工具、开发工具和部署工具可以通过注解来进行验证或进行部署。它的作用非常的多,例如:进行编译检查、生成说明文档、代码分析等。

    9.2 JDK提供的几个基本注解

      注解的语法比较简单,除了@符号的使用之外,它基本与Java固有的语法一致。java.lang.annotation.Annotation接口是所有的Annotation都必须实现的接口。在JDK1.5 之后,系统中已经建立了如下的三个内建标准Annotation类型,用户直接使用即可。

      系统内建的三种标准Annotation

        - @Override:覆写的Annotation

        - @Deprecated:不赞成使用的Annotation(过期、失效)

        - @SuppressWarnings:压制安全警告的Annotation(忽略警告)

    三种内定的标准Annotation如图9-1所示:

     

    9-1  三种内定的Annotation

      在Idea中输入@Override,然后按F3可以定位到@OverrideJava中的声明位置。

      另外,Java还提供了四种元注解,它们专门负责新注解的创建。

      四种元注解:

       @Target:表示该注解用于什么地方。

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

      可能的 ElemenetType 参数包括:

        ElemenetType.CONSTRUCTOR 构造器之前声明。

        ElemenetType.FIELD 域之前声明(包括 enum 实例)。

        ElemenetType.LOCAL_VARIABLE 局部变量之前声明。

        ElemenetType.METHOD 方法之前声明。

        ElemenetType.PACKAGE 包之前声明。

        ElemenetType.PARAMETER 方法参数之前声明。

        ElementType.ANNOTATION_TYPE 注解类型之前声明。

        ElemenetType.TYPE 类,接口(包括注解类型)或enum之前声明。

      @Retention:表示在什么级别保存该注解信息。

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

      可选的RetentionPolicy参数包括:

        RetentionPolicy.SOURCE 表示此注解信息只能保留在程序的源文件中,编译之后不会保存在编译好的类文件(*.class)之中。

        RetentionPolicy.CLASS 表示此注解信息保留在程序源文件(*.java)和编译之后的类文件(*.class)之中,在使用此类的时候,这些注解信息不会被加载到JVM之中,如果一个注解声明时没有制定范围,则默认是此范围。

        RetentionPolicy.RUNTIME 表示此注解信息保留在源文件(*.java)、类文件(*.class)和执行时也会加载。即JVM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。

      举一个例子,如@Override里面的Retention设为SOURCE,编译成功了就不要这一些检查的信息,相反,@Deprecated里面的Retention设为RUNTIME,表示除了在编译时会警告我们使用了哪个被 Deprecated的方法,在执行的时候也可以查出该方法是否被Deprecated

      @ Documented:将此注解包含在javadoc中。

      @ Inherited:允许子类继承父类中的注解。

      9.2.1 @Override

      该注解用在方法前面,用来标识该方法是重写父类的某个方法。@Override表示方法覆写的正确性。用来检测子类覆盖父类方法,是否与父类里方法签名一致。如果你不小心拼写错误,或者方法原型与要覆盖的方法不一致,则编译器就会发出错误提示。

    idea中输入@Override,然后按F3可以定位到@OverrideJava中的声明位置。如下就是@Override注解的声明:

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

      除了@符号以外,@Override的定义很像一个空的接口。@Target(ElementType.METHOD)表示@Override注解可以用于什么地方,这里只能用于METHOD(方法)前面;@Rectetion(RectetionPolicy.SOURCE)用来定义注解在哪一个级别可用,SOURCE表示源代码中,即@Override会被编译器丢弃。

    @Override使用举例:

    class A{
      public void disp(){
      }
      }
    
    class B extends A{
      @Override
      public void disp(int a){
      }
    }

      如果不写@Override,则编译没有任何问题,但是加上@Override之后,表示现在的disp是覆盖父类disp方法,但是却跟父类的方法原型不一致,所以此时会报错。

      9.2.2 @Deprecated

      该注解的作用是标记某个过时的类或方法。使用@Deprecated注释的Annotation本身是不建议使用的一个操作,表示已过时。当使用时,可能会出现了一个安全的警告信息。

      在idea中输入@Deprecated,然后按F3可以定位到@DeprecatedJava中的声明位置。如下就是@Deprecated注解的声明:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Deprecated {
    }

      @Documented表示@Deprecated注解包含在javadoc文档中。@Retention(RetentionPolicy.RUNTIME)表示在运行期间也保留@Deprecated注解。

      我们在idea中输入Date,然后按F3去查看java.util.Date这个类的说明时,可以发现,在该类中,有很多类似下面的语法:

      @Deprecated

          public Date(int year, int month, int date) {

              this(year, month, date, 0, 0, 0);

      }

      这些语法的特点是,在方法的前面加上了@Deprecated修饰之后,该方法会多一条横杠,表示此方法已经过期。如果我们还使用这个方法的话,编译器可能会提示警告信息。

      @Deprecated使用举例:

      @Deprecated //修饰类

    class C{

      @Deprecated //修饰属性

      private String name = "zhangsan";

      @Deprecated //修饰方法

      public int add(int a, int b){

        return a + b;

      }

    }

      9.2.3 @SuppressWarnings

      @SuppressWarnings 用于压制警告信息。通常写完一个程序之后可能会有这样那样的警告信息,可以利用@SuppressWarnings来消除。

      在idea中输入@Deprecated,然后按F3可以定位到@DeprecatedJava中的声明位置。如下就是@Deprecated注解的声明:

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

      @Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})表示@SuppressWarnings可以用于类、接口、枚举、域声明、方法、参数、构造器、局部变量的前面。@Retention(RetentionPolicy.SOURCE)表示  @SuppressWarnings只能在源文件中有效。内部是一个String[] value();数组属性,表示可以列举多项。

      @SuppressWarnings使用举例:

    public class Test {
      public static void main(String[] args) {
      @SuppressWarnings("all")
      int i = 0;
      }
    }

      定义变量i没有使用过,会提示警告,通过@SuppressWarning ("all") 取消所有警告。可以同时压制多个警告信息,只需要以数组的形式出现即可。  

        如:@SuppressWarnings({"unused", "serial", "deprecation"})

    关于@SuppressWarnings()中列举的含义参考下表:

    9.3 自定义注解

      9.3.1 定义注解

      定义简单的注解的格式:

        //@Target(适用场合)

        //@Retention(保存级别)

        //@Documented

        //@Inherited

        [public] @interface 注解名称{

          数据类型  变量名称();

        }

      

      如果定义注解时没有指定@Target元注解来限制它的使用范围,那么该注解可以使用在 ElementType枚举指定的任何一个元素前。否则,只能声明在@Target元注解指定的元素前。

      如果定义注解时没有指定@Retention元注解来说明它的生命周期,那么该注解默认的生命周期是保留在一个CLASS文件中。当然,也可以由一个@Retetion的元注解指定它的生命周期。

      所有的注解默认情况下都是使用@Documented进行注释,而且在生成javadoc的时候可以通过@Documented设置一些说明信息。

    下面是一个定义注解的实例:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface MyAnnotation {
    String value();
    }

      其中的@interface是一个关键字,用来声明一个注解。在设计annotation的时候必须把一个类型定义为@interface,而不能用classinterface关键字。所有的注解类都隐式继承于java.lang.annotation.Annotation,注解不允许显式继承于其他的接口。

      一个注解可以拥有多个成员,成员声明和接口方法声明类似,这里,我们仅定义了一个成员,成员的声明有以下几点限制:

        ·成员以无参无抛出异常的方式声明,如“boolean value(String str);”“boolean value() throws Exception等方式是非法的;

        ·可以通过default为成员指定一个默认值,如:“String level() default "LOW_LEVEL";”“int[] high() default {2, 3, 4};”是合法的,当然也可以不指定默认值;

        ·成员类型是受限的,合法的类型包括原始类型及其包装类、StringClassenums、注解类型,以及上述类型的数组类型。如“ForumService value();”“List foo();”是非法的。

        ·如果注解只有一个成员,则成员名通常取名为value(),这样在使用时可以忽略成员名和赋值号(=),如@ MyAnnotation ("使用注解的实例")。注解类拥有多个成员时,如果仅对value成员进行赋值则也可不使用赋值号,如果同时对多个成员进行赋值,则必须使用赋值号,如@DeclareParents (name = "张三", age = 25)

        ·注解类可以没有成员,没有成员的注解称为标识注解,解释程序以标识注解存在与否进行相应的处理;

        ·在操作中,对于一个注解而言有时候会固定其取值范围,只能取固定的几个值,那么这个时候实际上就需要依靠枚举。

      9.3.2 使用注解

      使用注解的语法:

      一般格式:

        @注解名(成员名1=成员值1, 成员名2=成员值2, ...)

      如果是成员的类型是数组:

        @注解名(成员名1={成员值1, 成员值2…}, 成员名2=成员值2, ...)

      下面是一个使用注解注解的实例。

    @MyAnnotation(value="my Annnotation")
    public class TestAnnotation {
      //
    }

      如果成员是数组类型,可以通过{}进行赋值,如boolean数组的成员可以设置为{true, false, true}。下面是几个注解使用的例子:

        ·多成员的注解

          @MyAnnotation(id= 2868724, synopsis = "Enable time-travel", engineer = "Mr. Peabody")

        ·一个成员的注解,且成员名为value,可以省略成员名和赋值符号

          @ MyAnnotation ("my Annnotation")

        ·无成员的注解

          @Override

        ·成员为字符串数组的注解

          @SuppressWarnings(value={"unchecked", "fallthrough"})

        ·成员为注解数组类型的注解

    //MyAnno.java
    import java.lang.annotation.*;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface MyAnno {
      String[] value();
    }
    //MyAnnotation.java
    import java.lang.annotation.*;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    
    public @interface MyAnnotation {
      String[] name();
      int age() default 25;
      MyAnno[] anno();
    }
    //TestAnnotation.java
    @MyAnnotation(name={"aaa", "bbb"}, anno={@MyAnno(value={"aaa", "bbb"}), @MyAnno(value={"ccc", "ddd", "eee"})})
    public class TestAnnotation {
      public static void main(String[] args) {
      }
    }

      9.3.3 得到注解

      一个注解要想让其变得有意义,则必须结合发射机制取得注解中设置的全部内容。对于生命周期为运行期间的注解,都可以通过反射获得该元素上的注解实例。

        1、声明在一个类中的注解

          可以通过该类 Class 对象的 getAnnotation getAnnotations 方法获得。

        2、声明在一个字段中的注解

          通过 Field 对象的 getAnnotation getAnnotations 方法获得

        3、声明在一个方法中的注解

          通过 Method 对象的 getAnnotation getAnnotations 方法获得

    感谢阅读。如果感觉此章对您有帮助,却又不想白瞟

                                     

  • 相关阅读:
    高速C/C++编译工具(ccache)
    CentOS7关闭自动下载更新
    GCC中同时使用动态和静态库链接的编译
    porting libiconv to android(arm)——libiconv-1.14.tar.gz
    编译cBPM-android-19—CodeBlocks—CentOS7— ndk10—编译libiconv和xerces-c
    Trying to build Xerces-C++ for Android
    计算机安全技术(第二版)第2版
    为android提供的部分第三方C/C++静态库—libsqlite—libuuid—libevent_static
    error: undefined reference to '__aeabi_uidiv'
    编译cBPM-android—CodeBlocks(全局、局部)参数设置—CentOS 7— android-ndk
  • 原文地址:https://www.cnblogs.com/springl/p/13549731.html
Copyright © 2020-2023  润新知