1. 反射内存图
2. 获取Class类对象
Class Class.forName(String 完整的包名.类名); √
根据用户提供的完整包名.类名,获取对应的Class类对象,【并且该方法可以强制加载对应的.class文件。】
Class 类名.class;
通过类名获取对应的Class对象属性
Class 类对象.getClass();
通过类对象,获取对应的Class类对象。
package com.qfedu.a_reflect;
public class GetClassObject {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> cls1 = Class.forName("com.qfedu.a_reflect.Person");
Class cls2 = Person.class;
Class<? extends Person> cls3 = new Person().getClass();
System.out.println(cls1);
System.out.println(cls2);
System.out.println(cls3);
System.out.println(cls1 == cls2);
System.out.println(cls3 == cls2);
System.out.println(cls3 == cls1);
}
}
3. 获取Constructor类对象
3.1 Constructor构造方法概述
构造方法我们有哪些内容需要考虑?
1. 参数 不确定,个数,类型,有无 【重载】
2. 权限修饰符 public private
3. 方法名 类名
public Person() {
}
构造方法在调用的过程中,首先会收到权限修饰符的约束,如果是public,类外可以通过构造方法创建对应的类对象,如果是私有化构造方法,只能在类内的方法中调用该构造方法。但是构造方法选择和【参数】有直接关系,而构造方法的名字是固定的,就是当前类名。
构造方法是依赖,参数类型区分的。
根据参数的类型,个数,顺序来选择执行对应的构造方法。
3.2 通过Class对象获取Constructor对象方法
Constructor[] getConstructors();
获取当前Class类对象内所有的非私有化构造方法类对象数组。
Constructor[] getDeclaredConstructors();
获取当前Class类对象内所有的构造方法类对象数组,包括私有化构造方法。【暴力反射】
Constructor getConstructor(Class... initParameterTypes); 【重点】
获取指定参数数据类型,顺序,个数的非私有化构造方法Constructor类对象。
例如:
public Person(int id, String name) {}
Class类对象.getConstructor(int.class, String.class);
int.class, String.class 这里需要的构造方法参数类型是(int, String)
public Person(int id) {}
Class类对象.getConstructor(int.class);
public Person() {}
Class类对象.getConstructor();
Class...
1. 这里需要的参数类型是Class类对象,用于约束当前方法所需的数据类型
2. ... 是不定长参数,参数个数不限制
Constructor getDeclaredConstructor(Class... initParameterTypes);
获取指定参数类型,顺序,个数对应的构造方法,可以获取私有化构造方法Constructor对象【暴力反射】
案例操作同上!!!
例如:
private Person(String name);
Class类对象.getDeclaredConstructor(String.class);
3.3 通过Constructor类对象创建对应数据类型类对象
利用Constructor对象,来创建对应数据类型的类对象。new 对象。需要通过Constructor类对象来调用对应的方法。
Object newInstance(Object... initParameters);【重点】
通过Constructor类对象调用,创建对应的类对象,需要的参数是当前Constructor类对象对应构造方法所需实际参数列表,需要和参数类型一致。
例如:
Constructor con1 ==> public Person();
Person p1 = (Person) con1.newInstance();
Constructor con2 ==> public Person(int);
Person p2 = (Person) con2.newInstance(1);
Constructor con3 ==> public Person(int, java.lang.String);
Person p3 = (Person) con3.newInstance(1, "骚磊");
那这行代码是不是就相当于 Person p = new Person(参数);
是的!!!
3.4 通过Constructor对象调用方法创建对应类对象的意义何在
这就是框架操作使用的思想!!!
配置文件:
A类 ==> 数据库A表
B类 ==> 数据库B表
类这边给予一个完整的包名.类名,通过读取文件中的配置内容,得到需要创建的类
对象是哪一个,借助于反射思想,完成类对象的创建。
同时还可以将数据库中数据库映射到类对象中。
3.5 私有化构造方法操作问题
直接操作使用对应私有化构造方法Constructor类对象,是没有权限操作的,因为private修饰。但是反射
【为所欲为!!!不破不立!!!】
这里可以给予私有化内容操作权限
void setAccessible(boolean flag);
该方法是可以通过【Constructor构造方法,Method成员方法,Field成员变量】调用,给予暴力反射私有化内容类外操作权限。
4. 获取Method类对象【重点】
4.1 Method成员方法概述
成员方法有哪些内容是我们关心的:
1. 返回值类型
2. 方法名
3. 形式参数列表
4. 权限修饰符
调用方法时
方法是条狗,哪里需要哪里吼,吼什么???
方法名(实际参数);
Person类
public void game();
public void game(String);
类内同名方法,需要通过方法的参数来区分,这里就是方法的【重载】;
如果需要获取一个Method成员方法类对象,我需要哪些内容???
1. 方法名
2. 参数类型,个数,顺序
4.2 通过Class类对象获取Method对象方法
Method[] getMethods();
获取类内的所有非私有化成员方法,包括从父类继承而来的子类可以使用的成员方法。
Method[] getDeclaredMethods();
获取类内的所有方法,包含私有化成员方法,但是不包括父类继承到子类成员方法。【暴力反射】
Method getMethod(String methodName, Class... parameterTypes);
根据指定的方法名,和对应的参数类型,个数,顺序获取对应的成员方法Method类对象,
可以获取类内的非私有化成员方法,和父类继承到子类的成员方法。
methodName 是方法名
Class... 不定长参数,根据方法的数据类型来选择对应的成员方法。
例如:
public void game();
Class类对象.getMethod("game");
public void game(String game);
Class类对象.getMethod("game", String.class);
Method getDeclaredMethod(String methodName, Class... parameterTypes);
根据指定的方法名,和对应的参数类型,个数,顺序,获取类内的成员方法,包含私有化成员方法,但是不包括父类继承到子类的方法。【暴力反射】
操作方式同上!!!
4.3 通过Method对象执行方法
涉及到一些方法
Object invoke(Object obj, Object... parameters);【用的很多】
obj:
执行调用当前方法的类对象
parameters:
不定长参数,当前方法执行所需的实际参数,要求符合形式参数列表要求参数类
型,个数和顺序。
返回值类型 Object
方法执行过程中可能会存在返回值,也有可能是void,Object表示所有,后期使
用过程中可以按照自己的需求进行数据类型强制转换
5. 获取Field类对象
5.1 Field成员变量概述
成员变量你操心什么,或者说你调用时你关注什么?
1. 变量名
5.2 通过该Class对象获取Field成员变量方法
Field[] getFields();
获取类内所有非私有化成员变量数组
Field[] getDeclaredFields();
获取类内所有成员变量数组,包括私有化成员变量【暴力反射】
Field getField(String fieldName);
根据成员变量名字,获取类内非私有化成员变量
Field getDeclaredField(String fieldName);
根据成员变量名字,获取类内任意权限修饰成员变量,包含私有化成员变量【暴力反射】
赋值成员变量
setter getter
成员变量的名字 ==> Field ==> 当前成员变量的数据类型 Class类对象
set + 成员变量的名字(数据类型 Class对象);
name.charAt(0) ==> n
n -= 32 ==> N
set + new StringBuilder(name).replace(0, 1, N);
==> BeanUtils
5.3 通过Field类对象赋值取值成员变量
void set(Object obj, Object value);
通过Field类对象调用,第一个参数是指定哪一个类对象中使用,第二个参数是对应当前成员变量的赋值数据。
Object get(Objec obj);
通过Field类对象调用,需要的参数是明确当前操作的是哪一个类对象中的成员变量
6. 反射学习要求
1. 想明白 Java文件 ==> .class文件之间的关系
2. 想明白 .class需要占用内存方法区的问题
3. .class占用的内存方法区空间 ==> Java文件之间的关系
4. 所有的今天讲到的反射方法,要求必须能够达到默写要求!!!
5. 反射不是一天能学会的!!!这是从更高层次角度分析得到的封装思想。