简单了解Java注解(Annotation)

2022-11-07 13:19:50 浏览数 (1)

目录

1、前言

2、JDK基本注解

2.1 @Override【重写】

2.2 @Deprecated【已过时 】

2.3 @SuppressWarnings(value = "unchecked") 【 压制编辑器警告】

3、JDK元注解【作用在其他注解的注解 】

3.1 @Retention【定义注解的保留策略】

3.2  @Target【标记这个注解应该是哪种Java 成员】

3.3  @Inherited【标记这个注解是继承于哪个注解类 】

3.4 @Documented【 标记这些注解是否包含在用户文档中】

4、自定义注解

5、注解分类

5.1 标记Annotation

5.2 元数据Annotation

6、提取Annotation信息


1、前言

  大家好,今天这篇博客是带大家简单了解一下 Java注解,让我们赶紧开始今天的旅程吧。

注解相关类都包含在java.lang.annotation包中。

2、JDK基本注解

2.1 @Override【重写】

  检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

  如果你使用MVC做为项目框架,在service层应该会经常看到。

2.2 @Deprecated【已过时 】

标记过时方法。

  已过时的方法会一条横线,我们把鼠标放上去,按住Ctrl点进去。

  这里就会发现它在这个方法上使用了@Deprecated这个注解。

2.3 @SuppressWarnings(value = "unchecked") 【 压制编辑器警告】

  指示编译器去忽略注解中声明的警告。

  这个如果你有强迫症,对你的代码容不得一点"黄色",就可以使用这个注解。

  我们现在加上这个注解。

3、JDK元注解【作用在其他注解的注解 】

3.1 @Retention【定义注解的保留策略】

标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。

3.1.1 Retention(RetentionPolicy.SOURCE)【一般情况下用不到】

注解仅存在于源码中,在class字节码文件中不包含。

3.1.2 @Retention(RetentionPolicy.CLASS)【如果括号里面上面什么都不写,默认】

 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得。

3.1.3 @Retention(RetentionPolicy.RUNTIME)【用的最多!!!】

注解会在class字节码文件中存在,在运行时可以通过反射获取到。

举例:这里我打开一个Controller。

  这个Controller上用了一个@RestController的注解,我们把鼠标放上去,按住Ctrl点进去。

  这上面的注解都是Java元注解。而这里面正好用到了@Retention(RetentionPolicy.RUNTIME)。

3.2  @Target【标记这个注解应该是哪种Java 成员】

指定被修饰的Annotation可以放置的位置(被修饰的目标)。 注:可以指定多个位置,例如:@Target({ElementType.METHOD, ElementType.TYPE}),也就是此注解可以在方法和类上面使用。

3.2.1   @Target(ElementType.TYPE) 【接口、类 (包括注释类型)或枚举声明

3.2.2   @Target(ElementType.FIELD)【字段声明(包括枚举常量)* 】

3.2.3   @Target(ElementType.METHOD) 【方法声明 】

3.2.4   @Target(ElementType.PARAMETER) 【方法参数声明】

3.2.5   @Target(ElementType.CONSTRUCTOR) 【构造函数声明】

3.2.5   @Target(ElementType.LOCAL_VARIABLE) 【局部变量声明】

3.2.6   @Target(ElementType.ANNOTATION_TYPE)【 注释类型声明

3.2.7   @Target(ElementType.PACKAGE) 【 包声明

举例:还是上面Controller用的@RestController

  它这里使用@Target(ElementType.TYPE),我们来试试看能不能作用在其他的地方。

  在这里我们发现,它作用于属性和方法上都报错了,所以它真的只能作用于接口或类上!大家如果有兴趣现在可以把自己用过的注解一个一个点进去看看。

3.3  @Inherited【标记这个注解是继承于哪个注解类 】

指定被修饰的Annotation将具有继承性 【默认 注解并没有继承于任何子类】

举例:以@Transactional这个注解为例  

 我们点进去看看。

我们就可以看到@Inherited这个注解,只要带有@Inherited这个元注解,说明@Transactional这个注解有继承性。

假如A这个接口使用了@Transactional这个注解,因为@Transactional这个注解上使用@Inherited这个注解,那B这个实现类去实现A这个接口,那B实现的所有方法里面都有事务,这就是继承性。

3.4 @Documented【 标记这些注解是否包含在用户文档中】

指定被修饰的该Annotation可以被javadoc工具提取成文档。

 这里推荐看: IDEA如何使用javadoc工具导出API 文档和注解@Documented的具体作用_英杰的学习日记的博客-CSDN博客

https://blog.csdn.net/weixin_53041251/article/details/122333117

4、自定义注解

自定义注解,顾名思义就是我们自己定义的注解。

  像@RestController,@GetMapping等等,这些都是第三方框架提供给我们的注解,它们都是自定义的注解。  

举例:

 这上面就是一个自定义的注解,是不是感觉挺简单的,接下来我们来打开一个Demo。

我们在这个@MyAnnotation1自定义注解上使用了@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD}),所以它能同时作用于类和属性上。

而且我们看到了括号里有我们在注解里声明的属性name,如果我们将其省略,只写值。

 我们会发现它报错了,但有一种情况下,它不会报错,就是我们把属性名改成value

  当然,这个前提条件是你只输入一个属性的值。如果有多个属性的值,他还是会报错的。

  小结:

只有名字为“value”属性,赋值时可以省略属性名。 使用@interface关键字, 其定义过程与定义接口非常类似, 需要注意的是: Annotation的成员变量在Annotation定义中是以无参的方法形式来声明的, 其方法名和返回值类型定义了该成员变量的名字和类型, 而且我们还可以使用default关键字为这个成员变量设定默认值。 例如:

代码语言:javascript复制
@Inherited

@Retention(RetentionPolicy.RUNTIME)
   
@Target({ElementType.METHOD, ElementType.TYPE})
   
public @interface Tag {

     String name() default "该叫啥才好呢?";


     String description() default "这家伙很懒, 啥也没留下...";

}

5、注解分类

根据Annotation是否包含成员变量,可以把Annotation分为两类:

5.1 标记Annotation

没有成员变量的Annotation; 这种Annotation仅利用自身的存在与否来提供信息。

5.2 元数据Annotation

包含成员变量的Annotation; 它们可以接受(和提供)更多的元数据。

6、提取Annotation信息

使用AnnotatedElement接口中的方法提取注解中的数据。 例如: Class/Constructor/Field/Method/Package这些类都实现了AnnotatedElement接口。 注:只有当定义Annotation时使用了@Retention(RetentionPolicy.RUNTIME)修饰,JVM才会在装载class文件时提取保存在class文件中的Annotation,该Annotation才会在运行时可见,这样我们才能够解析。

 举例:

 我们打开一个测试类,实验一下。

在上面我们说了class实现了AnnotatedElement接口,而AnnotatedElement有一个getAnnotation的方法,我们调用,最后得到一个注解对象annotation,我们再用annotation去点name这个属性,打印。  

0 人点赞