文章目录
注解&反射
注解
概念
注解(Annotation),也叫元数据,标签。与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明。
作用
①编写文档:生成API文档
②代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
③编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【eg. Override】
使用
语法:@ + 注解的名称 – 比如@Override
注解的三要素
需要有一个注解;(有一个标签)
使用这个注解(这个注解贴在什么地方,不同注解作用域不同,需查看元注解@Target标注的范围);
第三方程序为注解实现功能;
JDK四大内置注解
@Override注解用于标识方法重写,例如当前类中重写tostring()方法
@Deprecated注解用于标识方法已过时
@SuppressWarings注解用于抑制编译器警告,直白的讲就是消除Eclipse上那条黄色警告线,但编译器里关于这条警告的信息还在。
@SafeVarargs抑制堆污染警告(单独警告),直白的讲就是使用泛型和可变参数搭配使用将会产生的编译器警告,可以使用@SuppressWarnings消除警告,后来在Java7引入了新的注解,就是@SafeVarargs,如果开发人员确信某个使用了可变参数的方法,在与泛型类一起使用时不会出现类型安全问题,就可以用这个注解进行声明,这样编译器就不会报警告。
JDK的元注解
概念
元注解的作用就是用于定义其他注解,是由JAVA为我们提供的,不能更改,从JAVA5.0开始一共为我们提供了四个元注解。
@Target
@Target作用
用于描述注解的使用范围,也就是说使用了@Target去定义一个注解,那么可以决定定义好的注解能用在什么地方
@Target取值
@Target的取值使用ElementType,ElementType的相关说明可以通过JDK文档查询,也可以直接查看其源码
- CONSTRUCTOR:用于描述构造器
- FIELD:用于描述域
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention
@Retention作用
用于描述注解的生命周期,也就是说这个注解在什么范围内有效,注解的生命周期和三个阶段有关:源代码阶段、CLASS文件中有效、运行时有效,故其取值也就三个值,分别代表着三个阶段
@Retention取值
@Retention的取值适用RetentionPoicy,RetentionPoicy的相关说明可以通过JDK文档查询,也可以通过查看源码
-
SOURCE:在源文件中有效(即源文件保留)
-
CLASS:在class文件中有效(即class保留)
-
RUNTIME:在运行时有效(即运行时保留)
@Documented
@Documented作用
使用@Documented定义后的注解,在该注解使用后,如果导出API文档,会将该注解相关的信息可以被例如javadoc此类的工具文档化。
Documented是一个标记注解,没有成员。
@Inherited
@Inherited作用
使用@Inherited定义的注解具备继承性
假设一个注解在定义时,使用了@Inherited,然后该注解在一个类上使用,如果这个类有子类,那么通过反射我们可以从类的子类上获取到同样的注解
自定义注解
语法:
@Target(类 方法 构造方法 字段 参数)(指定作用范围)默认不指定范围的时候,全局都可使用
@Retention(源文件 字节码文件 运行时)(约束生命周期)
@Documented 生成API文档
@Inherited 子类可以获得父类上面的注解信息
public @interface 注解名{
类型 属性名() default 默认值;//default可以不写(类型:基本数据类型、String、Class、枚举)
}
使用注解
@注解名(属性名=”值”)
@注解名(属性名={”值1”,”值2”}) //注解类型为数组
反射
概念
在运行时期,动态的去获取类中相关信息(公有的和私有的 字段、构造方法、方法 、注解)
作用
- 增加程序的灵活性,避免将程序写死到代码里(解除硬编码的问题);
- Java的反射机制它知道类的基本结构,可以动态的去获取类这样的结构的结构;
- 可以让程序员在不知道其它程序员会有什么类的时候就编写完成自己的代码;
- 反射的优点:灵活,功能强大(可以拿到私有的…);
反射的缺点:破坏封装,影响性能;
Class实例
概念
一些类型的字节码对象
Class 类的实例表示正在运行的 Java 应用程序中的类和接口;
枚举是一种类,注解Annotation是一种接口;
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象;
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象;
注意 :
同一种类型不管通过什么方式得到Class的实例都是相等的;一个类型的字节码对象只有一份;
语法
获取字节码对象
类: 1.类名.class 2.对象名.getClass() 3.Class.forName(全限定名:包名+类名)
接口: 1.接口名.class 2.Class.forName(全限定名:包名+类名)
数组: 1.对象名.getClass() 2.数组类型.class
基本数据类型:1.基本数据类型.class 2.对应包装类型.Type
Void:类名.class
如果是获取公有的不用设置访问权限,如果是私有的则需要设置访问权限:私有化对象名.setAccessible(true);
获取构造方法
公共无参的 :字节码对象.newInstance,公共有参的:字节码对象.getConstructor(参数的字节码);
获取方法
字节码对象.getMethod(方法名称,参数字节码); 执行:方法对象.invoke(对象,实际参数);
获取字段
字节码对象.getFiled(字段名称);设置值 :字段对象.set(对象,实际参数);
获取注解
字节码对象.getAnnotation(注解的字节码);注解对象.对应的方法(获取属性值)