Java 反射
程序在
运行期间
,可以动态
的获取一个类的信息
(属性、方法、构造方法、方法的形参、父类、父接口、类上的泛型、包、注解)。
类对象
类加载的产物是类对象,而一个类有且只会被加载一次。
类对象的获取方式
- 类.class
Class<LightComponent> lightComponentClass = LightComponent.class;
- 对象.getClass()
Class<? extends LightComponent> aClass1 = component.getClass();
- Class.forName(“包.类”)
Class<?> aClass = Class.forName("day26.Component");
类对象常见的类基本操作方法
- getClassLoader() : 获取加载该类的 加载器
- getName() : 获取类的名字(包名 + 类名)
- getSimpleName(): 只获取类名(不包含包名)
双亲委托机制
加载一个类主要是通过 类加载器 ClassLoader 实现的, Java中提供了三个 ClassLoader。
-
BootStrapClassLoader: 只负责加载 JDK 官方提供的核心类
-
ExtClassLoader: 负责加载 JDK 官方提供的 扩展库
-
AppClassLoader: 负责加载 自定义的类 和 第三方 jar
1. 保证一个类只会被加载一次、2.防止核心类被篡改
Constructor
获取 类中的 构造方法 Constructor
- getDeclaredConstructors() : 获取 类中所有的 构造方法,返回一个 Constructor[]
- getConstructors() : 获取 类中 所有 公开 的构造方法 (被 public 修饰的)
- getDeclaredConstructor(Class…) : 获取指定的构造方法
- getConstructor(Class…) : 获取指定的 公开的 构造方法
Constructor 常见的方法
- newInstance(obj…) : 使用Constructor 构造方法 创建对象
- setAccessible(boolean) : 是否允许破坏封装,绕过访问权限,默认是false
- getName() : 获取构造方法的方法名
- getModifiers() : 获取修饰符 (权限修饰符、静态修饰符 , final, abstract, native, …)
- Modifier 是标识 修饰符 ,内置了 大量的 is方法 判断是否是某种修饰符 ,内置 大量的 常量,标记 修饰符
- getParameterTypes() : 获取 构造方法的参数列表,返回 Class[]
- getParameterCount() : 获取 参数列表的个数
Field 属性
- getDeclaredFields() : 获取当前类 声明的所有属性
- getFields() : 获取 该类 所有的 公开属性 (包含继承的属性)
- getDeclaredField(String fieldName) : 根据名字 获取指定的属性
- getField(String fieldName) : 根据名字,获取 指定的 公开属性 (包含继承的属性)
Field 属性中常见的方法
-
set(obj, val) : 给 obj 对象的 属性 设置 val 值
-
setXxxx(obj, val) : 给 obj 对象的属性(类型是基本数据类型) 设置 对应的 值
-
get(obj) : 获取 obj 对象的 属性值 ,返回 Object
-
getXxxx(obj) : 获取 obj对象的属性值(类型是基本数据类型)
-
trySetAccessible() : 尝试访问,如果不能访问 返回 false
-
setAccessible(boolean) : 是否破坏封装
-
getModifiers() : 获取属性修饰符
-
getName() : 获取属性名
-
getType() : 获取 属性类型
练习:
有一个 Map 集合, 数据格式如下
{
id: 10,
username: "张三"
}
==> 通过 反射技术 将 Map集合中的数据,添加到 User (id, username) 对象中
Method 方法
- getDeclaredMethods() : 获取当前类中定义的所有方法
- getMethods() : 获取 类中所有公开方法(包含继承的方法)
- getDeclaredMethod(name, Class<?>…) : 获取当前类中声明的指定方法
- getMethod(name, Class<?>…) : 获取 指定的公开方法 (包含继承的方法)
Method 中常见的方法
-
getName() : 获取方法名
-
getModifiers() : 获取修饰符
-
getReturnType() : 获取返回值的类型
-
getParameterTypes() : 获取方法参数列表类型
-
getParameterCount() : 获取参数个数
-
getExceptionTypes() : 获取方法 声明的时候 throws 的异常
-
invoke(obj, params…) : 调用方法
获取 父类、父接口
- getSuperclass() : 获取一个类的 直接父类, 返回 Class
- getGenericSuperclass() : 获取一个类的直接父类(包含泛型信息), 返回 Type
**如果父类没有使用泛型,那么2个方法返回的结果是一样的 **
- getInterfaces() : 获取一个类实现的所有接口, 返回 Class[]
- getGenericInterfaces() : 获取一个类实现的所有接口(包含泛型信息)、返回Type[]
练习:
定义一个方法、用来获取 一个类 中 所有的 属性 (包含所有父类的属性)
public static List<Field> getAllFields(Class<?> clz) ;
定义一个方法、用来获取一个类的所有父类(不包含接口)
public static List<Class<?>> getAllSuperClasses(Class<?> clz) ;
定义一个方法、用来获取一个类的所有接口(包含父接口)
public static List<Class<?>> getAllSuperInterfaces(Class<?> clz);
定义一个方法、用来获取一个类的所有方法(包含父类定义的)
public static List<Method> getAllMethods(Class<?> clz) ;
注解
注解是对代码进行注释的一种手段,它可以参与编译和运行~
元注解
元注解 用来注解在其他注解上的注解
-
@Target : 用来定义注解可以书写的位置, 例如 类上、方法上、属性上、参数上、构造方法上
- ElementType.TYPE : 标记该注解可以写在类上、接口上
- ElementType.METHOD : 标记该注解可以写在方法上
- ElementType.FIELD : 标记该注解可以写在属性上
- ElementType.CONSTRUCTOR : 标记该注解可以写在构造方法上
-
@Retention : 用来定义注解在什么情况下可以使用
- RetentionPolicy.SOURCE : 注解只能在源码中使用、代码编译后该注解会不存在
- RetentionPolicy.CLASS : 注解可以保留在字节码中、程序在运行的时候不可用
- RetentionPolicy.RUNTIME : 注解可以在运行阶段使用、可以配合反射实现某些特殊效果
-
@Documented : 用来标记该注解在生成文档的时候,是否在文档中生成
-
@Inherited : 用来标记该注解是否允许 子类继承
-
@Repeatable : 用来标记该注解是否支持多次注释
自定义注解
注解使用 @interface 修饰符
注解 支持的 成员类型
* 1. 8种基本数据类型
* 2. 字符串
* 3. 枚举类型
* 4. Class
* 5. 注解
* 6. 上述所有类型的 数组 表示形式