java 注解 基本知识

1.注解

注解到底是干什么的?_张铎-CSDN博客

注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记。标记可以加在包、类,属性、方法,方法的参数以及局部变量上。
第一阶段最早在继承父类然后方法重载的时候就接触过注解。
@override就是一个标识,说明这是一个重写的方法。实际编译为字节码文件时就没有用了,只是在源码进行标识和判断方法重载的格式是否正确。
有一些注解则具备功能性
比如@getting 和@webServlet(将servlet配置到web.xml中,即映射到tomcat根目录)

1.1 创建注解

注解就是接口,在创建的时候设置为接口即可,注解要单独放在一个包里,包名annotation 中文翻译即注解
image

此时的接口还只是一个普通接口,需要在interface前加上@符号 才能转为注解类
image

此时这个注解就可以被使用了,但是此时的注解仅仅具备标识作用,可以被写在类上或者构造方法上,一个对象上可以被施加多个注解
image

1.2 注解的属性

注解可以设置属性,注意以下几点:
数据类型 属性名() default 值

  1. 设置数据类型与设置类时一致,但要注意设置基本数据类型时要给原始类型,不能给包裹类型
  2. 属性名后要加小括号
  3. default用于设置默认值
  4. 设置多个值,比如设置为数组时,要用大括号表示数组{},数组内各个元素用逗号隔开

实例:
设置注解属性
image

使用注解并给注解传值,传多个值时要用逗号隔开,并且写成k-v的格式
image

1.3 元注解

所谓元注解就是声明在注解上的注解,元注解是注解的一种声明,用于设置注解。
JDK1.5开始提供注解,给了4个注解,常用的是其中两个注解

@Retention 保留期,声明注解的存活时间
@Documented 保留本类中的注解并能够被javadoc识别
@Target 指定注解的运行地方(类/方法/变量等)
@Inherited 注解是否可以被子类继承

1.3.1 @Retention

Retention的意思是保留期(或者叫存活期)的意思,是指定该注解在JVM中的存活期的注解
存活期:源码阶段(.java文件) 编译阶段(.class) 运行阶段
不设置存活期时,默认存活期到编译阶段

RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到JVM 中,默认时@Retention就设置为这个值
RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到JVM 中,如果希望能在代码运行时取到注解的值,必须设置为这个值

源码说明:
这个注解只有一个属性,用于设置注解的保留期,该注解用枚举保存了三个值,根据传入的值确定设置的保留期
实际执行时,JAVA文件会被编译为字节码文件,此时代码从上至下执行,遇到注解时就会进入,然后读取@Retention以确定当前注解的保存期,再决定是否将这个注解保存在字节码中
image

代码:
image

使用:
image

1.3.2 @Target

指定当前声明的注解可运行的范围的标记,通过该注解可以指定声明的注解具体运行在类/方法/变量上等

ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造方法进行注解
ElementType.FIELD 可以给属性进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法内的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

源码说明:
这个注解只有一个属性,用于设置的注解的可运行地点,该注解用枚举保存了十个值,根据传入的值确定注解能作用的地方
image

代码:
image

使用:
设置注解允许放的位置,可以只设置一个,也可以设置多个,设置多个时用大括号括起来,值之间用逗号隔开
image

此时如果注解放的地方不对,就会报错,如图放在构造方法上就报错了
image

1.4 获取类上的注解

JAVA提供了封装好的反射方法,基于Class对象,能获取到加在类上的注解

Class对象 . getAnnotation(注解名.class) 返回类中指定名字的注解,此时得到的是一个注解对象 Annotation
Class对象 . getAnnotation() 返回类中所有注解,此时得到的是一个注解数组 Annotation[]
注解名 变量名 = (注解名) Annotation对象 通过上面的方法获得的Annotation对象需要强制转换为具体的注解,才能获取详细的属性
Annotation对象 . annotationType() 获取到注解对象的全类名

注意:
getAnnotation()返回的是父接口类型的对象,就比如取一个对象,返回的是一个object对象,如果希望获取到对象中的具体的属性,必须向下造型。

方法:
image

实例 获取指定的注解:
①某个类设置的注解如图,一个类上可以设置多个注解,类中的方法或者变量也可以单独设置注解
image

②在test测试类中创建一个指向类的Class对象,再调用方法获取到类中指定名字的注解
image

③获取到注解对象后,可以进一步取值,注意必须使用强制转换
image

实例 获取多个注解:
获取到类中所有注解后,循环输出
image

1.5 获取类的构造器上的注解

如果需要获取加在类的构造器上的注解,不能通过类获取,得通过类的构造器

Constructor 变量名 = Class对象 . getConstructor() 获取无参构造器
Constructor 变量名 = Class对象 . getConstructor(String.class, String.class) 通过参数类型获取有参的构造器,显然这得先知道想要的构造器的具体参数表
Constructor对象 . getAnnotation(注解名.class) 返回类的构造器上指定名字的注解,此时得到的是一个注解对象 Annotation
Constructor对象 . getAnnotation() 返回类的构造器上所有注解,此时得到的是一个注解数组 Annotation[]
注解名 变量名 = (注解名) Annotation对象 通过上面的方法获得的Annotation对象需要强制转换为具体的注解,才能获取详细的属性

注意:
getAnnotation()返回的是父接口类型的对象,就比如取一个对象,返回的是一个object对象,如果希望获取到对象中的具体的属性,必须向下造型。

实例:
Clazz指向的类的构造器:
image

对应的注解属性:
image

代码与结果:
①获取到的注解只是类的构造器上的值。
②注解的属性值被定义时就会修改,未被定义时就保持默认值
image

1.6 获取类的属性上的注解

如果需要取到类的属性上的注解,需要先获取到类的属性

Field 变量名 = Class对象 . getField( "变量名" ) 获取类中指定名字的公开的成员变量,返回一个对象
Field[] 变量名 = Class对象 . getFields() 获取类中所有公开的成员变量,包括从父类继承的公开的成员变量,返回一个对象数组
Field 变量名 = Class对象 . getDeclaredField( "变量名" ); 获取类中指定名字的成员变量,即便这个变量是否公开,返回一个对象
Field[] 变量名 = Class对象 . getDeclaredFields(); 获取类中所有的成员变量,但不包括从父类继承的成员变量,返回一个对象数组
Field对象 . getAnnotation(注解名.class) 返回类的构造器上指定名字的注解,此时得到的是一个注解对象 Annotation
Field对象 . getAnnotation() 返回类的构造器上所有注解,此时得到的是一个注解数组 Annotation[]

注意:
通过类的属性获取到属性上的注解,直接就是注解对象,而不是父接口对象Annotation,不需要强制类型转换

实例:
image

posted @ 2021-08-12 23:05  夏·舍  阅读(87)  评论(0编辑  收藏  举报