美文网首页Java
3、注解(一)

3、注解(一)

作者: 唯老 | 来源:发表于2019-08-09 00:28 被阅读1次

    一、概要

    注解对于开发人员来讲既熟悉又陌生,熟悉是因为只要你是做开发,
    Java注解又称为标注,是Java从1.5开始支持加入源码的特殊语法元数据;对修饰的元素进行解释说明

    二、应用场景

    • 动态配置信息
    • 配合反射实现程序逻辑
    • 代码格式检查,比如Override、Deprecated、NonNull等,便于IDE能够检查出代码错误

    三 常见内置注解(了解)

    1、@Override

    标记注解,不需要设置属性值;只能添加在方法的前面,用于标记该方法是复写的父类中的某个方法,如果在父类没有的方法前面加上@Override注解,编译器会报错:

    2、 @Deprecated

    标记注解,不需要设置属性值;作用是标记当前的类或者方法或者字段等已经不再被推荐使用了,可能在未来的版本中会删除

    3、@SuppressWarnings

    可以对构造方法、变量、方法、包、参数标记,用于告知编译器忽略指定的警告,不用再编译完成后出现警告信息

    4、 @Nullable

    用于标记方法参数或者返回值可以为空;

    5、@NonNull

    用于标记方法参数或者返回值不能为空,如果为空编译器会报警告;

    四、自定义注解(重点)

    1、说明

    注解跟 classs, interface,enum一样,注解也属于一种类型。

    2 、语法格式

    1. 格式
       public @interface 注解名 {定义体}
      
    2. 说明
      他定义的形式跟接口很类似,不过前面多了一个 @ 符号。
    3. 举个栗子
      public @interface TestAnnotation {
      }
      

    3 、注解的应用

    1. 说明
      注解可以用在类,接口 枚举等任何地方
    2. 举个栗子
      @TestAnnotation
      public class User {
        @TestAnnotation
        private String name;
        @TestAnnotation
       public void setName(@TestAnnotation name){
        }
      }
      @TestAnnotation
      public enum Color {
      }
      @TestAnnotation
      public interface TestService {
      }
      

    4、注解的属性

    1. 说明
      注解的属性也叫做成员变量。注解只有成员变量,没有方法。
      注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。
    2. 语法格式
      public @interface TestAnnotation {
        类型 变量() default 默认值;
      }
      
    3. 类型可选值
      • 基本类型(int,float,boolean,byte,double,char,long,short)
      • String类型
      • Class类型
      • enum类型
      • Annotation类型
      • 以上所有类型的数组
    4. 例如
      public @interface TestAnnotationField {
        String value()
       int id() default "0";
       String hello() default "";
        Stirng[] detail();
      }
      /*
       * 1. 只能用public或默认(default)这两个访问权修饰.例如,String value()
       * 2. 可以设置defaul值 如果设置了default值,在使用的时候可以省略不写
       */
      
    5. 使用
      // 赋值的方式是在注解的括号内以 value="" 形式,多个属性之前用 ,隔开。
      @TestAnnotationField(value='test', id=1, hello="坤坤", detail=['1','2','3'])
      public class User {
      }
      
    6. 注意如果属性的名称是value时可以省略
      public @interface TestAnnoValue {
        String value()
      }
      @TestAnnoValue("value可以省不写")
      public class User {
      }
      

    五、元注解

    用于修饰注解的注解叫元注解,内置的元注解
    @Retention、@Documented、@Target、@Inherited、@Repeatable(jdk1.8新增)5 种。

    1、@Retention(重点)

    1. 作用
      表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
    2. 语法格式
      public @interface Retention {
          RetentionPolicy value();
      }
      
    3. 可选值
      可选值 说明
      RetentionPolicy.SOURCE 在源文件中有效(即源文件保留)
      RetentionPolicy.CLASS 在class文件中有效(即class保留)
      RetentionPolicy.RUNTIME 在运行时有效(即运行时保留)
    4. 举个栗子
      @Retention(RetentionPolicy.SOURCE)
      public @interface RetentionDemo {
      }
      

    2、@Target(重点)

    1. 作用
      Target 是目标的意思,@Target 指定了注解可以修饰那些元素,当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。
    2. 语法格式
      public @interface Target {
          ElementType[] value();
      }
      
    3. 可选值
      类型 说明
      ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
      ElementType.CONSTRUCTOR 可以给构造方法进行注解
      ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
      ElementType.FIELD 可以给属性进行注解
      ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
      ElementType.METHOD 可以给方法进行注解
      ElementType.PACKAGE 可以给一个包进行注解
      ElementType.PARAMETER 可以给一个方法内的参数进行注解
      ElementType.TYPE_USE 可以用于标注任意类型

    3、@Inherited(掌握)

    1. 作用
      使用此注解声明出来的自定义注解,在使用此自定义注解时,
    2. 注意事项
      如果注解在类上面时,子类会自动继承此注解,否则的话,子类不会继承此注解。也就是说使用Inherited声明出来的注解,只有在类上使用时才会有效,对方法,属性等其他无效
    3. 语法格式
      public @interface Inherited {
      }
      
    4. 举个栗子
      /**
       * 没有使用Inherited元注解,表示此注解用在类上时,不会被子类所继承
       * @author zhangwei
       */
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.TYPE_USE)
      public @interface NoInheritedAnnotation {
          String value();
      }
      @Target(ElementType.TYPE_USE)
      @Retention(RetentionPolicy.RUNTIME)
      @Inherited
      public @interface InheritedAnnotation {
          String value();
      }
      
      @InheritedAnnotation("使用Inherited的注解class")
      @NoInheritedAnnotation("未使用Inherited的注解class")
      public class Parent {
          @InheritedAnnotation("使用Inherited的注解 field")
          @NoInheritedAnnotation("未使用Inherited的注解field")
          public String name;
          @InheritedAnnotation("使用Inherited的注解 method")
          @NoInheritedAnnotation("未使用Inherited的注解 method")
          public String getName() {
              return name;
          }
      }
      

    4、@Repeatable

    1. 作用
      java8 新增的,允许在同一修饰的类型(类,属性,或方法)的多次使用同一个注解
    2. 举个栗子
      // jdk8 之前
      @Target(ElementType.TYPE)
      @Retention(RetentionPolicy.RUNTIME)
      public @interface Annotation8 {
          String [] value();
      }
      //使用
      @Annotation8({"/update","/add"})
      public class TestAnno{
      }
      
      /*
       * 1. 定义需要重复的注解
       * 3.在需要重复使用的注解上的值指向容器的.class
       */
      @Repeatable(RepeatableContainer.class)
      public @interface RepeatableAnnotation {
           String value();
      }
      /*
       * 2.定义个一容器注解
       */
      public @interface RepeatableContainer {
          RepeatableAnnotation[] value();
      }
      // 测试
      public class RepeatTest {
          @RepeatableAnnotation("1")
          @RepeatableAnnotation("2")
          public void toDo() {
          }
      }
      

    5、@Documented(了解)

    1. 作用
      用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

    七、注解与反射

    1、说明

    在以下的类中Class Constructor Field Method Package等类都实现了AnnotatedElement接口相关API
    同时配合反射提供的api我们就可以在程序运行时(@Retention(RetentionPolicy.RUNTIME))拿到注解

    2、注解相关api

    方法 说明
    getDeclaredAnnotations() 获取声明过的所有Annotation
    getAnnotations() 获取所有的Annotation
    isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断annotation是否存在
    getAnnotations(Class annotationType) 获取一个指定的annotation类型

    3、举个栗子

    1. 综合栗子
      @Target(ElementType.FIELD)
      @Retention(RetentionPolicy.RUNTIME)
      public @interface FieldAnnotation {
          String name();
          int id() default 0;
      }
      
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.METHOD)
      public @interface MethodAnnotation {
          String value();
      }
      
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.TYPE_USE)
      public @interface TypeAnnotation {
          String value();
          int id() default 0;
      }
      
      @TypeAnnotation(value = "注解在类上使用", id = 1)
      public class TestBean {
          @FieldAnnotation(name = "注解在变量上使用")
          private String name;
          @MethodAnnotation(value = "在方法上使用")
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
      }
      
    2. 注解继承
      @Inherited
      @Target(ElementType.TYPE_USE)
      @Retention(RetentionPolicy.RUNTIME)
      public @interface ParentAnnotation {
          String id();
      }
      

    相关文章

      网友评论

        本文标题:3、注解(一)

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