day15反射

day15反射,第1张

反射

一、类加载
	1.类加载的过程   //了解
		(1)加载类进内存
			对每一个class文件创建一个class文件对象,用来描述类的信息
			
		(2)连接类
			校验加载进来的东西是否符合语法的要求
		
		(3)类的初始化
			先初始化父类,再初始化子类

	2.类的初始化时机
		(1)创建类的实例   //Student s = new Student();
		(2)调用类的类方法   //Student.show();
		(3)访问类或者接口的类变量,或者为该类变量赋值
		(4)使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
		(5)初始化某个类的子类
		(6)直接使用java.exe命令来运行某个主类(idea中点击运行按钮)
				//什么时候需要用就什么时候加载

二、类加载器
	1.类加载器的功能是什么?
		负责将.class文件加载到内存中,并为之生成对应的 java.lang.Class 对象(字节码文件对象)

	2.特点
		针对于不同的类和文件,java会提供不同的类加载器
			//比如Student和ArrayList 它们的类加载器是不同的
			
三、反射
	1.反射的概述
		反射:就是利用.class文件对象(而不是java文件对象)来获取类中的构造方法、成员变量、成员方法,并且无视权限修饰符。

	
	2.获取class文件对象的方式
		(1)类名.class 
			举例:Class c1 = Student.class;   //最方便
		
		(2)对象名.getClass()方法
			举例:Student s1 = new Student();
					Class c2 = s1.getClass();
		
		(3)Class.forName(全类名)   //开发中最常用
			//全类名:  包名+类名             
				*写法:demo2.Student
				*在idea中怎么写全类名? 
						选中你想要 *** 作的文件 ------------ 右键 ----------- Copy Reference 
			举例:Class c3 = Class.forName("demo2.Student");
	

	3.反射获取构造方法并使用
		(1)Constructor[] getConstructors()返回所有"公共"构造方法对象的数组  //获取所有的public修饰的构造方法对象
		(2)Constructor[] getDeclaredConstructors() 返回"所有"构造方法对象的数组  //获取的是所有的构造方法
		
		(3)Constructor getConstructor(Class... parameterTypes) 返回单个"公共"构造方法对象  //获取的是单个的public修饰的构造方法
		(4)Constructor getDeclaredConstructor(Class... parameterTypes)返回单个构造方法对象 //获取单个构造方法

		创建对象的方法
			T newInstance(Object...initargs) 根据指定的构造方法创建对象
				//newInstance方法中参数要和构造方法的参数对应起来
		
	
			//使用反射的第一句代码永远都是获取字节码文件对象
		代码实现:
			public class Demo2 {
				public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
					//获取字节码文件对象
					Class c1 = Class.forName("demo2.Student");

					//获取构造方法的对象
					Constructor constructor = c1.getConstructor(int.class);
					Object o = constructor.newInstance(13);
					System.out.println(o);
				}
			}

	4.暴力反射
		(1)使用场景
			当我们要使用private修饰的构造方法、成员变量、成员方法对象去使用的时候

		(2)注意两点
			*使用带declared的获取方法
			*临时修改权限
				constructor.setAccessible(true);   //表示暂时允许我访问

				代码举例:
					public class Demo2 {
						public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
							//获取字节码文件对象
							Class c1 = Class.forName("demo2.Student");

							//获取构造方法的对象
							Constructor constructor = c1.getDeclaredConstructor(int.class);
							constructor.setAccessible(true);
							Object o = constructor.newInstance(13);
							System.out.println(o);
						}
					}


四、反射获取成员变量并使用
	1.回想一下,以前我们怎么给一个对象的成员变量赋值?
		Student s1 = new Student();
		s1.age = 13;
		//也就是说,想要给一个对象的成员变量赋值,需要先有一个对象,第二个是要赋的值

	2.相关方法
		(1)Field[] getFields() 返回所有"公共"成员变量对象的数组  //获取的是所有的public修饰的成员变量对象
		(2)Field[] getDeclaredFields() 返回"所有"成员变量对象的数组  //获取的是所有的修饰符修饰的成员变量对象
		
		(3)Field getField(String name) 返回单个"公共"成员变量对象  //获取的是单个的public修饰的成员变量对象
		(4)Field getDeclaredField(String name) 返回单个成员变量对象  //获取的是单个的任意修饰符修饰的成员变量对象
			//参数 name指的是 成员变量的名称

		反射中给成员变量对象赋值的方法
			void set(Object obj,Object value) 给obj对象的成员变量赋值为value
				参数:第一个参数obj(相当于上面的s1) 指的是你要给哪个"对象"赋值    第二个参数  value(相当于上面的13) 指的是要给成员变量赋的具体的值

			代码实现:
				public class Demo3 {
					public static void main(String[] args) throws Exception{
						Class c1 = Class.forName("demo2.Student");

						/*Constructor constructor = c1.getConstructor();
						Object o1 = constructor.newInstance();*/
						Object o = c1.getConstructor().newInstance();

						//获取成员变量的对象
						Field namel = c1.getField("namel");

						namel.set(o,"王小二");

						System.out.println(o);
					}
				}

五、反射获取成员方法并使用
1.回忆以前我们怎么调用成员方法
Student s1 = new Student();
s1.show();
//前提:调用成员方法需要现有一个对象

	2.相关方法
			//面试题: 反射中获取getMethods和getDeclaredMethods两个方法的区别?
		(1)Method[] getMethods() 返回所有"公共"成员方法对象的数组,包括继承的  // 获取所有public修饰的方法对象  +  包括继承过来的
		(2)Method[] getDeclaredMethods() 返回"所有"成员方法对象的数组,不包括继承的  //获取所有任意修饰符修饰的方法对象  (不包括继承的)
		
		(3)Method getMethod(String name, Class... parameterTypes)返回单个公共成员方法对象
		(4)Method getDeclaredMethod(String name, Class... parameterTypes)返回单个成员方法对象
			//参数: String类型的mame  指的是方法的名称     parameterTypes:指的是方法的参数类型

		反射中调用成员方法的方法
			Object invoke(Object obj,Object... args) 调用obj对象的成员方法,参数是args,返回值是Object类型
				//参数: obj指的是调用方法的对象(相当于上面的s1)   args:是你调用方法时需要穿进去的实际参数
				//返回值 :指的是方法的返回值

			//代码实现:
				public class Demo4 {
						public static void main(String[] args) throws Exception {
							//获取字节码文件对象
							Class c1 = Class.forName("demo2.Student");

							//创建Student对象
							Object o = c1.getConstructor().newInstance();

							//获取show方法的对象(暴力反射)
							Method show = c1.getDeclaredMethod("show", String.class);
							show.setAccessible(true);
							Object o1 = show.invoke(null, "比奥利奥二");
							Object o1 = show.invoke(o, "比奥利奥二");
							System.out.println(o1);
						}
					}
			
				方法的分类:
					*非静态方法
						无参无返回值
						无参有返回值
						有参无返回值
						有参有返回值
					
					*静态方法
						无参无返回值
						无参有返回值
						有参无返回值
						有参有返回值
						
						
						
六、相关案例
	1.越过泛型检查
		泛型检查是在"编译期间"用来规范开发人员的书写,等编译结束生成字节码文件之后,泛型就会被擦除掉。
						
						
	2.反射结合配置文件使用
		//使用配置文件就是为了解耦合

模块化 //了解
一、模块化的概述
1.什么是模块
在Idea中我们在开发项目之前,需要新建一个项目(project),在项目下又会创建多个module,这个module就是模块

	2.模块的特点
		不同的模块之间是不能相互访问的

	3.学习模块化的前提
		JDK必须大于等于9


二、模块的基本使用   //Maven,也可以实现模块间的相互访问
	比如:在A模块中使用B模块的东西,该怎么配置
		//A是调用者     B是被调用者

	第一步:创建A和B两个模块(创建时一定要注意jdk的版本要大于等于9)
	第二步:在A和B的src文件夹下各自创建一个module-info的文件
	第三步:在B的module-info文件中配置
				exports + 包名

			在A的module-info文件中配置
				requires + 模块名


三、面向接口编程的思想
	调用者只能知道调用的接口名和抽象方法的名称,而看不到具体的实现(为了保证代码的安全性)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/871599.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存