• Java-注解


    前言

    JavaSE中,注解的使用目的比较简单,例如标记过时的功能、抑制警告等等。在JavaEE中,注解占据了更重要的角色,现在流行框架Spring... Mybatis等都支持注解开发

    1、注解使用示例

    Java中有很多注解,我们举例三个常见的注解

    1.1、@Override

    作用域:只能写在方法上

    含义:表示这个方法是重写的父类的方法

    重写了父类的方法,如果添加上这个注解,那么重写的方法如果方法名称错误或者返回值类型错误,编译就会报错提示,反之没加注解,则不会提示

    案例(观察sayHi3、sayHi4方法,都想要重写sayHi2方法,但是方法名都写错了,查看结果)

    package com.tcc.entity;
    
    import java.io.Serializable;
    
    /**
     * @author 宇辰
     * @date 2022/9/26-11:27
     **/
    public class User extends Person {
    
        public static void main(String[] args) {
            User user = new User();
            user.sayHi(); // 我是用户
        }
    
        @Override
        public void sayHi() {
            System.out.println("我是用户");
        }
    
        @Override
        public void sayHi3() {
            System.out.println("想要重写父类方法sayHi2");
        }
    
        public void sayHi4() {
            System.out.println("想要重写父类方法sayHi2");
        }
    }
    
    class Person {
        private String name;
        private String sex;
    
        public void sayHi(){
            System.out.println("我是人");
        }
    
        public void sayHi2(){
            System.out.println("被重写的方法");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    结果(可以看到带注解的会报错,因为在父类中没有找到被重写的方法sayHi3)

    在这里插入图片描述

    1.2、@Deprecated

    作用域:只能写在方法上

    含义:表示这个方法已经过时,不建议使用,但仍可以使用

    被这个注解描述过的方法,调用的时候会在上面会显示被划掉的特殊样式

    案例(Date日期类型很多方法都过时了)

    在这里插入图片描述

    调用结果

    在这里插入图片描述

    1.3、@SuppressWarnings

    作用域:可以写在任何位置,类、方法、属性…等

    含义:抑制编译器的警告,不提示警告消息

    参数

    • 抑制单类型警告@SuppressWarnings(“unchecked”)、
      抑制多类型警告@SuppressWarnings(“unchecked”,“rawtypes)、
      抑制所有类型警告:@SuppressWarnings(“all”)
    • all: 抑制所有警告
    • boxing :抑制装箱、拆箱操作时候的警告
    • cast: 抑制映射相关的警告
    • dep-ann: 抑制启用注解的警告
    • deprecation: 抑制过期方法警告
    • fallthrough: 抑制在 switch 中缺失 breaks 的警告
    • finally :抑制 finally 模块没有返回的警告
    • hiding: 抑制相对于隐藏变量的局部变量的警告
    • incomplete-switch: 忽略不完整的 switch 语句
    • nls: 忽略非 nls 格式的字符
    • null :忽略对 null 的操作
    • rawtypes: 使用 generics 时忽略没有指定相应的类型
    • restriction: 抑制禁止使用劝阻或禁止引用的警告
    • serial: 忽略在 serializable 类中没有声明 serialVersionUID 变量
    • static-access: 抑制不正确的静态访问方式警告
    • synthetic-access: 抑制子类没有按最优方法访问内部类的警告
    • unchecked: 抑制没有进行类型检查操作的警告
    • unqualified-field-access : 抑制没有权限访问的域的警告
    • unused: 抑制没被使用过的代码的警告

    使用Eclipse的话,如果参数定义了没使用,会有个黄色警告。

    使用Idea的话,则是参数名称颜色变灰,都表示一个意思,警告

    没有被使用,并且没有添加注解

    没有被使用,但是使用了注解

    在这里插入图片描述

    2、自定义注解

    注解一般在反射机制中用的多

    • 定义新的Annotation类型使用@interface关键字
    • 自定义注解自动继承了java.lang.annotation.Annotation接口
    • Annotation的成员变量在Annotation定义中以无参数方法的形式来生命,其方法名和返回值定义了该成员的名字和类型。。我们成为配置参数。类型只能是八种基本数据类型:String、Class、Enum、Annotation以上所有类型的数组。
    • 可以在定义Annotation的成员变量是为其指定初始值,指定成员变量的初始值可使用default关键字
    • 如果只有一个参数成员,建议使用参数名为value
    • 如果定义的注解含有配置参数,那么使用时必须指定参数值,除非有默认的值,格式是:参数名=参数值,如果只有一个参数成员,且名称为value,则可以省略value=,直接写值
    • 没有成员定义的Annotation成为标记,包含成员变量的注解称为元数据注解

    自定义注解必须配上注解的含义才有意义(在注解上写文档注解表名该注解含义)

    无参注解


    定义

    package com.tcc.anno;
    
    /**
     * @author 宇辰
     * @date 2022/9/26-11:27
     **/
    public @interface MyAnno {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用

    在这里插入图片描述

    有参注解


    定义

    package com.tcc.anno;
    
    /**
     * @author 宇辰
     * @date 2022/9/26-11:27
     **/
    public @interface MyAnno {
    
        String value();
    
        // 有默认值的注解,有默认值的话,使用注解可以不写该参数的值
        //String value() default "demo";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    使用

    在这里插入图片描述

    3、元注解

    元注解是定义在注解上的注解,用于修饰其他注解

    JDK5.0提供了4个标准的meta-annotation类型,分别是:

    • Retention:指定该注解的生命周期
    • Target:指定该注解使用的地方
    • Documented:指定是否在JavaDoc文档中显示
    • Inherited:指定子类是否继承父类的这个注解

    3.1、Retention注解

    只能用于修饰一个Annotation定义,用于指定该Annotation的生命周期,@Retention包含一个@RetentionPolicy类型的成员变量,使用@Rentention时,必须为该value成员变量指定值

    • RetentionPolicy.SOURCE:在源文件中有效(即源文件中保留),编译器直接丢掉这种策略的注解
    • RetentionPolicy.CLASS(默认):在class文件中保留(即编译文件中保留),当运行Java程序时,JVM不会保留注解
    • RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行Java程序时,JVM会保留注解,程序可以通过反射来获取该注解

    下面分别举例

    SOURCE


    1. 在自定义注解上,添加该注解,并且参数为RetentionPolicy.SOURCE

      package com.tcc.anno;
      
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      
      /**
       * @author 宇辰
       * @date 2022/9/26-11:27
       **/
      @Retention(RetentionPolicy.SOURCE)
      public @interface MyAnno {
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    2. 把注解写到main方法上

      在这里插入图片描述

    3. 运行main方法,查看编译后的文件是否保留了该注解(并没有保留)

      在这里插入图片描述

    CLASS


    1. 在自定义注解上,添加该注解,并且参数为RetentionPolicy.CLASS

      package com.tcc.anno;
      
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      
      /**
       * @author 宇辰
       * @date 2022/9/26-11:27
       **/
      @Retention(RetentionPolicy.CLASS)
      public @interface MyAnno {
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    2. 把注解写到main方法上

    3. 运行main方法,查看编译后的文件是否保留了该注解(保留了)

      在这里插入图片描述

    RUNTIME


    1. 在自定义注解上,添加该注解,并且参数为RetentionPolicy.RUNTIME

    2. 把注解写到自定义的实体类上

      package com.tcc.entity;
      
      import com.tcc.anno.MyAnno;
      
      /**
       * @author 宇辰
       * @date 2022/10/22-14:09
       **/
      @MyAnno
      public class User {
          private String name;
          private String sex;
      
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    3. Main方法中,使用反射获得该注解(只有值为RUNTIME的才可以使用反射获取注解)

      package com.tcc.test;
      
      
      import com.tcc.anno.MyAnno;
      import com.tcc.entity.User;
      
      /**
       * @author 宇辰
       * @date 2022/8/31-8:53
       **/
      public class Test {
          public static void main(String[] args){
              Class<User> userClass = User.class;
              MyAnno annotation = userClass.getAnnotation(MyAnno.class);
              System.out.println(annotation.toString()); // @com.tcc.anno.MyAnno()
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    3.2、Target注解

    用于修饰Annotation定义,用于指定被修饰的Annotation能用于修饰那些程序元素

    @Target也包含一个名为value的成员变量,参数类型为ElementType的枚举类

    ElementType

    参数有很多,这里就不一一讲解, 这里只演示ElementType.METHOD,作用在方法上

    package com.tcc.test;
    
    
    import com.tcc.anno.MyAnno;
    import com.tcc.entity.User;
    
    /**
     * @author 宇辰
     * @date 2022/8/31-8:53
     **/
    // @MyAnno  写在类上,报错
    public class Test {
    
        @MyAnno // 只能写在方法上面
        public static void main(String[] args){
            Class<User> userClass = User.class;
            MyAnno annotation = userClass.getAnnotation(MyAnno.class);
            System.out.println(annotation.toString()); // @com.tcc.anno.MyAnno()
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3.3、Documented注解

    表明该注解是否显示在生成的JavaDoc文档中,没有参数,用作标识

    默认情况下JavaDoc是不包括注解的

    举例


    在这里插入图片描述

    如何生成JavaDoc文档


    在这里插入图片描述

    3.4、Inherited注解

    被它修饰的Annotation将具有继承性,如果某个类使用了被@Inherited修饰的Annotation,则其子类自动具有该注解

    举例


    1. 在自定义注解上添加该注解

      package com.tcc.anno;
      
      import java.lang.annotation.*;
      
      /**
       * @author 宇辰
       * @date 2022/9/26-11:27
       **/
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.TYPE_USE)
      @Documented
      @Inherited
      public @interface MyAnno {
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    2. 在实体类(User)中使用该注解

      package com.tcc.entity;
      
      import com.tcc.anno.MyAnno;
      
      /**
       * @author 宇辰
       * @date 2022/10/22-14:09
       **/
      @MyAnno
      public class User {
          private String name;
          private String sex;
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    3. 在Main方法所在的类(Test)中继承User实体类,然后使用反射获取(Test)类上的注解

      package com.tcc.test;
      
      
      import com.tcc.anno.MyAnno;
      import com.tcc.entity.User;
      
      /**
       * @author 宇辰
       * @date 2022/8/31-8:53
       **/
      public class Test extends User {
          public static void main(String[] args){
              Class<Test> testClass = Test.class;
              MyAnno annotation = testClass.getAnnotation(MyAnno.class);
              System.out.println(annotation.toString()); // @com.tcc.anno.MyAnno()    因为继承了User类,这个类上有MyAnno注解,所以它自己也有
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    4、JDK8新特性(可重复注解)

    @Repeatable(MyAnnos.class)里面参数使用自己定义的注解

    准备

    在一个地方重复使用两次注解,查看结果(会报错)


    在这里插入图片描述

    4.1、JDK8之前解决办法

    思路:

    ​ 创建一个注解,参数为想重复写的注解数组,然后在想要写的地方使用该注解,参数填入注解数组即可实现写多个重复注解

    1. 创建一个MyAnnos注解,定义类型为MyAnno数组的参数

      package com.tcc.anno;
      
      /**
       * @author 宇辰
       * @date 2022/10/22-15:34
       **/
      public interface MyAnnos {
          MyAnno[] value();
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    2. User类上使用MyAnnos注解,参数传入两个相同的MyAnno注解

      package com.tcc.entity;
      
      import com.tcc.anno.MyAnno;
      import com.tcc.anno.MyAnnos;
      
      /**
       * @author 宇辰
       * @date 2022/10/22-14:09
       **/
      /*@MyAnno("test1")
      @MyAnno("test2")*/
      @MyAnnos({@MyAnno("test1"),@MyAnno("test2")})
      public class User {
          private String name;
          private String sex;
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

    4.2、JDK8解决办法

    使用注解:@Repeatable(MyAnnos.class)

    注意:

    • 参数里面自定义的注解的元注解,要与里面的参数里面的注解的元要保持一致,即子有,父也要有
    • 作用域可以不保持一致,但是一定要比参数注解的生命周期长
    1. 使用我们上面定义的MyAnnos注解

      package com.tcc.anno;
      
      /**
       * @author 宇辰
       * @date 2022/10/22-15:34
       **/
      public @interface MyAnnos {
          MyAnno[] value();
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    2. 在需要重复使用的注解上面添加:@Repeatable(MyAnnos.class)注解即可

      package com.tcc.anno;
      
      import java.lang.annotation.*;
      
      /**
       * @author 宇辰
       * @date 2022/10/22-15:34
       **/
      // 因为参数注解也有这些属性,所以父注解也需要有
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.TYPE_USE)
      @Documented
      @Inherited
      public @interface MyAnnos {
          MyAnno[] value();
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
    3. 使用

      package com.tcc.entity;
      
      import com.tcc.anno.MyAnno;
      
      /**
       * @author 宇辰
       * @date 2022/10/22-14:09
       **/
      @MyAnno("test1")
      @MyAnno("test2") // 不报错了
      //@MyAnnos({@MyAnno("test1"),@MyAnno("test2")})
      public class User {
          private String name;
          private String sex;
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    5、JDK8新特性(类型注解)

    在Java8中,ElementType新增了两个值

    • TYPE_PARAMETER:作用在类型参数上( 比如:泛型)
    • TYPE_USE:作用在类型上(包含上面那个)

    举例


    1. 修改MyAnno注解上的@Target元注解参数

      package com.tcc.anno;
      
      import java.lang.annotation.*;
      
      /**
       * @author 宇辰
       * @date 2022/9/26-11:27
       **/
      @Retention(RetentionPolicy.CLASS)
      @Target(ElementType.TYPE_USE)
      @Documented
      @Inherited
      public @interface MyAnno {
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    2. 使用

      在这里插入图片描述

  • 相关阅读:
    SpringBoot整合Redis
    乡村新业态 | 直播电商引领经济发展,拓世法宝AI智能直播一体机助推乡村振兴
    服务器CPU和电脑的CPU区别是什么
    python+Django 使用apscheduler实现定时任务 管理调度
    Node学习笔记之Node简介
    智能晾衣架(二)--功能实现
    【Golang开发面经】B站(两轮技术面)
    尚医通-预约挂号
    【C++】STL梳理
    实验5-2——网络yum源的配置
  • 原文地址:https://blog.csdn.net/qq_57404736/article/details/127463226