反射【重点,难点】

1. 反射内存图

反射【重点,难点】_第1张图片

2. 获取Class类对象

Class Class.forName(String 完整的包名.类名); √
	根据用户提供的完整包名.类名,获取对应的Class类对象,【并且该方法可以强制加载对应的.class文件。】
	
Class 类名.class;
	通过类名获取对应的Class对象属性
	
Class 类对象.getClass();
	通过类对象,获取对应的Class类对象。
/*
国庆 25 get 国庆目前负债50!!!
靓琦 25 forName
*/
package com.qfedu.a_reflect;

public class GetClassObject {
     
	public static void main(String[] args) throws ClassNotFoundException {
     
		/*
		 * 通过指定的包名.类名获取对应的Class对象
		 */
		Class<?> cls1 = Class.forName("com.qfedu.a_reflect.Person");
		
		/*
		 * 通过类名获取Class对象,获取类属性
		 */
		Class cls2 = Person.class;
		
		/*
		 * 通过类对象获取对应的Class对象
		 */
		Class<? extends Person> cls3 = new Person().getClass();
		
		System.out.println(cls1);
		System.out.println(cls2);
		System.out.println(cls3);
		
		
		/*
		 * 以上三个Class对象是同一个对象,因为Person.java文件对应的.class字节码文件
		 * 在内存中有且只占一块方法区内存空间,.class字节码文件有且只加载一次。
		 */
		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. 反射不是一天能学会的!!!这是从更高层次角度分析得到的封装思想。

你可能感兴趣的:(反射【重点,难点】)