首页 > 编程语言 >Java注解

Java注解

时间:2022-10-29 15:44:06浏览次数:52  
标签:Java java class annotation LogAnnotation 注解 public

1.Java注解的描述

java注解又叫做java标注,是java的一种注释机制,在jdk5.0引入。其可以作用在类、方法、变量、参数和包上。另外,其可以通过反射来获取注解标注的内容。可以说注解就是实现了Annotation的接口

2.Java注解的分类

Java注解分类的话,大致可以分为三类,分别是标准注解,元注解与自定义注解。

  • 标准注解
    标准注解就是java内置的注解,主要有@Override,@Deprecated,@SuppressWarnings,@FunctionalInterface
    • @Override:这个注解的作用主要是检查该注解标注的方法是否是重写方法,如果不是重写方法的话编译会不通过会报错。

    • @Deprecated:这个注解的作用主要是标记该方法可能要废弃了,使用的话会报个警告。

    • @SuppressWarnings:这个注解主要是告诉编译器要忽视一些警告。其常见的参数有:

      参数 作用
      deprecation 使用了不赞成使用的类或方法的警告
      unchecked 执行了未检查的转换时的警告,例如使用集合时没有用泛型来指定集合保存的类型
      fallthrough 当switch程序块两个case之间没有break时
      path 在类路径,源文件路径中有不存在的路径时的警告
      serial 在可序列化的类上缺少serialVersionUID定义时的警告
      all 所有的警告
    • @FunctionalInterface:用于指示被修饰的接口是函数式接口,在jdk8被引入

  • 元注解
    主要有@Retention,@Documented,@Target,@Inherited,@Repeatable
    • @Retention:用来定义该注解在哪个级别可用,也就是注解的生命周期,一个注解只能定义一个级别。具体有三个级别:
      image

      参数 描述
      SOURCE 在编译时被丢弃,不包含在类文件中,既不会参与编译也不会在运行时起到什么作用
      CLASS JVM加载时被丢弃,包含在类文件中,但是不能在运行时被获取到,默认值
      RUNTIME 由JVM加载包含在类文件中,能在运行时被获取到,一般开发自定义注解使用该级别
    • @Documented:表示该注解能不能出现在javadoc中,被该元注解修饰的注解表示能出现在javadoc中,如果没有被该元注解修饰,则是不会出现在javadoc中

    • @Target:用来表示该注解的适用范围,一个注解可以有多个适用范围,每个使用范围之间在大括号内用逗号隔开。如:
      @Target({ElementType.TYPE, ElementType.METHOD})
      使用范围的值总共有十个:
      image

      参数 描述
      TYPE 应用于类、接口(包括注解类型)或枚举
      FIELD 应用于字段(包括枚举常量)
      METHOD 应用于方法
      PARAMETER 应用于形参,也就是方法的参数
      CONSTRUCTOR 应用于构造函数
      LOCAL_VARIABLE 应用于局部变量
      ANNOTATION_TYPE 应用于注解
      PACKAGE 应用于包
      TYPE_PARAMETER 应用于类型参数,JDK1.8引入
      TYPE_USE 应用于任何类型,JDK1.8引入
    • @Inherited:该注解说明子类可以继承父类的注解,也就是说,如果被该元注解修饰的注解,能够在子类继承父类的时候把注解也继承过去。但是这边有一个需要注意的点,就是被该元注解修饰的注解只有应用在类上的时候才能够被继承过去,应用在方法或其他地方时是没有的,这边我刚开始就是用在了方法上,然后一直没效果。例子:

      注解:
      package com.mcj.music.annotation;
      
      import java.lang.annotation.*;
      
      /**
       * @author mcj
       * @date 2022/10/28 20:27
       * @email [email protected]
       * @description 日志有关的自定义注解
       */
      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.TYPE, ElementType.METHOD})
      @Inherited
      public @interface LogAnnotation {
      
          String value() default "";
      
      }
      
      父类:
      package com.mcj.music.annotation;
      
      /**
       * @author mcj
       * @date 2022/10/29 9:40
       * @email [email protected]
       * @description
       */
      @LogAnnotation("测试inherited注解")
      public class TestInherited {
      }
      
      子类:
      package com.mcj.music.annotation;
      
      /**
       * @author mcj
       * @date 2022/10/29 9:40
       * @email [email protected]
       * @description
       */
      public class ChildTestInherited extends TestInherited{
      
          public static void main(String[] args) {
      	 System.out.println(TestInherited.class.isAnnotationPresent(LogAnnotation.class));
      	 System.out.println(ChildTestInherited.class.isAnnotationPresent(LogAnnotation.class));
          }
      
      }
      

      输出结果:
      image
      去掉@Inherited注解的结果:
      image
      image

    • @Repeatable:表示被该元注解修饰的注解能够重复使用,也就是可以在一个方法上使用多次该注解,可以说将该注解用一个数组容器包了起来。例子:

      //LogAnnotation注解
      package com.mcj.music.annotation;
      
      import java.lang.annotation.*;
      
      /**
       * @author mcj
       * @date 2022/10/28 20:27
       * @email [email protected]
       * @description 日志有关的自定义注解
       */
      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.TYPE, ElementType.METHOD})
      @Repeatable(LogAnnotations.class)
      public @interface LogAnnotation {
      
          String value() default "";
      
      }
      
      
      // LogAnnotations注解
      package com.mcj.music.annotation;
      
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      /**
       * @author mcj
       * @date 2022/10/29 9:52
       * @email [email protected]
       * @description
       */
      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.TYPE, ElementType.METHOD})
      public @interface LogAnnotations {
          LogAnnotation[] value();
      }
      
      //测试类:
      package com.mcj.music.annotation;
      
      import java.lang.annotation.Annotation;
      import java.lang.reflect.Array;
      import java.util.Arrays;
      
      /**
       * @author mcj
       * @date 2022/10/29 9:55
       * @email [email protected]
       * @description
       */
      @LogAnnotation("测试repeatable1")
      @LogAnnotation("测试repeatable2")
      public class TestRepeatable {
      
          public static void main(String[] args) {
              Annotation[] annotations = TestRepeatable.class.getAnnotations();
              System.out.println(annotations.length);
              System.out.println(Arrays.toString(annotations));
          }
      
      }
      

      运行结果:
      image
      可以从结果看出,虽然注解的长度是1,但是它里面有两个不同的值
      PS:需要注意的是@Repeatable注解声明的注解(也就是LogAnnotation)要比@Repeatable值中的注解(也就是LogAnnotations)的作用范围大或相等,可用级别小或相等。

  • 自定义注解
    自定义注解大致可以分为三步:1.定义注解,2.配置注解,3.解析注解
    • 1.定义注解-也就是声明一个注解,创建一个注解对象
      注解与方法、变量、枚举等声明方式相似,唯一不同的是其关键字为@interface,也就是只要是声明时使用了该关键字,底层在实现的时候都会继承java.lang.annotation.Annotation接口。
      public @interface LogAnnotation {
      
      }
      
      在注解的方法体里面只能写一个东西:注解类型元素,也就是注解的属性。其格式为:
      修饰符 数据类型 属性名() default 默认值;
      其中修饰符必须是public,所以可以直接不写,其默认值即是public
      其中可以写的数据类型有:八种基本类型(int,short,long,double,byte,char,boolean,float),String,Class,注解类型,枚举类以及上面任一种类型的数组形式。
      其中的属性名是自定义的
      其中的()并不是定义参数的地方,只是一种语法而已
      default表示该属性的默认值,其默认值与前面的数据类型一致,有个要注意的点是如果没有设置默认值,则该注解在使用的时候一定要赋值。如下:
      public @interface LogAnnotation {
      
          // 值描述
          String value() default "";
      	
          // 名字
          String name();
      
      }
      
    • 2.配置注解-也就是对上面定义的注解配置其作用范围及生命周期
      配置注解则是利用上面记录的几种元注解对自定义的注解进行修饰,来描述自定义注解的生命周期与作用范围。如:
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.METHOD)
      public @interface LogAnnotation {
      
          // 值描述
          String value() default "";
      	
          // 名字
          String name();
      
      }
      
    • 3.解析注解-也就是在程序运行时检测注解,并进行一系列操作
      注解的解析主要是通过java的反射来实现的,可以通过反射来获取相应的类、方法或字段,通过获取的类、方法、字段来判断其上是否使用了该注解,使用的话则获取该注解与该注解内各个元素的值。例子如下:
      package com.mcj.music.annotation;
      
      import java.lang.reflect.Method;
      
      /**
       * @author mcj
       * @date 2022/10/29 14:26
       * @email [email protected]
       * @description
       */
      public class TestAnnotation {
      
          @LogAnnotation(name = "mcj", value = "10.09测试")
          public void printString() {
              System.out.println("输出一个字符串");
          }
      
          public static void main(String[] args) {
              Class<TestAnnotation> testAnnotationClass = TestAnnotation.class;
              Method[] methods = testAnnotationClass.getMethods();
              for (Method method : methods) {
                  if (method.isAnnotationPresent(LogAnnotation.class)) {
                      LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
                      String name = annotation.name();
                      String value = annotation.value();
                      System.out.println(String.format("方法%s用了LogAnnotation注解,注解值name为:%s,value为:%s", method.getName(), name, value));
                  }
              }
          }
      
      }
      
      输出结果:
      image
      描述:方法中的TestAnnotation.class就是利用反射获取TestAnnotation这个类对象,testAnnotationClass.getMethods()这个则是根据类对象获取该类中所有的方法,method.isAnnotationPresent(LogAnnotation.class)则是判断方法是否存在LogAnnotation注解,需要注意的是要看注解是标注再什么上面,如果是类上面则是类.isAnnotationPresent()如果是字段则是字段.isAnnotationPresent()这里是标注在方法上的。最后的getAnnotation()则是获取这个注解,然后利用使用枚举值的方式就可以获取注解中的属性值了。

3.总结

java的注解主要是对我们的开发起到一个辅助作用,帮助我们更容易的进行开发。其中自定义注解,主要是的就是那五个元注解,不过经常用的也就@Retention和@Target这两个元注解,另外对于注解的解析则是利用了java的反射机制。

标签:Java,java,class,annotation,LogAnnotation,注解,public
From: https://www.cnblogs.com/mcj123/p/16833838.html

相关文章

  • JAVA-图片打乱
    packagecom.itheima;importjavax.swing.*;importjava.util.Random;publicclassshuzu09{publicstaticvoidmain(String[]args){//创建窗体对......
  • Javascript学习随笔
    JavaScript:简称JS,是一个运行在客户端/浏览器的【解释性】【弱类型】【面向对象】脚本语言。想要运行js需要运行环境:浏览器自带js解释器node.js需要安装环境编译型:在......
  • java pta第二次阶段性总结
    一、前言     经过这三次的pta训练,我对java再一次有了一个新的认识,这三次比起之前难度更大,所涉及的知识点更多。第4、5次作业是在前几次作业上的再次拓展,由三角形拓......
  • JAVA-图片展示
    packagecom.itheima;importjavax.swing.*;publicclassshuzu08{publicstaticvoidmain(String[]args){//创建窗体对象JFramejf=new......
  • javaSE day02
    字面量888888  80 说明一下首先“id”不足8个字符,所以要加”\t“补全,但是”20204206“满足八个字符,添加就会加8个空格,不添加就会造成与后文相连,所以上......
  • java基础-->数组
    **#数组介绍数组指的是一种容器,可以用来存储同种数据类型的多个值。数组容器在存储数据的时候,需要结合隐式转换考虑。下面写的都是一维数组,多维数组就是多个中括号即......
  • 从新开始学JAVA - IDEA
    什么是IDE全称是集成开发环境(IDE,IntegratedDevelopmentEnvironment)是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成......
  • spring注解--切面(AOP)相关注解
    切面(AOP)相关注解Spring支持AspectJ的注解式切面编程。@Aspect声明一个切面(类上)使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。@After在......
  • spring注解--@Bean的属性支持
    @Bean的属性支持@Scope设置Spring容器如何新建Bean实例(方法上,得有@Bean)其设置类型包括:·Singleton(单例,一个Spring容器中只有一个bean实例,默认模式),·Protetype(每......
  • spring注解--声明注解
    1.声明bean的注解@Component 组件,通用的注解方式@Component作用:调用无参构造创建一个bean对象,并把对象存入spring的IOC容器,交由spring容器进行管理。相当于在xml中配......