反射

反射

一、类加载器

1.1类加载

类加载(类初始化化):

不出意外JVM连续完成以下三步骤:

​ 类的加载

​ 1.class文件读入内存,建立一个java.lang.Class对象

​ 2.任何类被使用时,系统都会建立一个java.lang.Class对象

​ 类的连接

​ 验证阶段: 检验类的内部结构 和其他类协调一致

​ 准备阶段:为类变量分配内存,设置默认初始化值

​ 解析阶段:将类的二进制数据中的符号引用替换为直接引用

​ 类的初始化

​ 类变量初始化步骤

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WWjMxRvG-1616143801437)(C:\Users\wcy\AppData\Roaming\Typora\typora-user-images\image-20210319131310436.png)]

类变量初始化时机(首次使用)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WfEgDVdT-1616143801441)(C:\Users\wcy\AppData\Roaming\Typora\typora-user-images\image-20210319131430909.png)]

1.2类加载器

负责把.class文件加载到内存中 生成对应的java.lang.Class对象

JVM的类加载机制:

​ 全盘负责:加载某类 该类依赖的引用和依赖的其他类 也该由这个类加载器负责(除非说明是别的类加载器)

​ 父类委托:加载某类,先让父类加载器试图加载此类,无法加载,才尝试用自己的类路径加载

​ 缓存机制:加载过的类都放到缓存区,缓存区没有,再读取二进制数据,并转换为class对象存到缓存区。

Bootstrap -> Platform -> System (父—>子)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYZ0VnOU-1616143801443)(C:\Users\wcy\AppData\Roaming\Typora\typora-user-images\image-20210319132656894.png)]

    • ClassLoadergetParent() 返回父类加载器进行委派。
    • static ClassLoadergetSystemClassLoader() 返回用于委派的系统类加载器。

二、反射

2.1 反射概述

Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展

2.2 获取Class类的对象

我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象,也就是类型为Class类型的对象这里我们提供三种方式获取Class类型的对象

	1.使用类的class属性来获取该类对应的Class对象。举例: Student.class将会返回Student类对应的Class对象

​ 2.调用对象的getClass()方法,返回该对象所属类对应的Class对象,该方法是Object类中的方法,所有的Java对象都可以调用该方法

​ 3.使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径

Class<Student> c1 = Student.class;
System.out.println(c1);//class m3d19Reflect.Student

Class<Student> c2 = Student.class;
System.out.println(c1==c2);//true

Student s = new Student();
Class<? extends Student> c3 = s.getClass();
System.out.println(c1==c3);//true

Class<?> c4 = Class.forName("m3d19Reflect.Student");
System.out.println(c1==c4);//true

2.3反射获取构造方法

先获取class对象 再用

​ getConstructors 返回所有pubic构造方法对象数组

​ getDeclaredConstructors返回所有构造方法对象数组

​ getConstructor 返回指定pubic构造方法对象(参数为构造方法参数类型.class(基本类型也可以.class))

​ getDeclaredConstructor返回指定构造方法对象

Class<?> c = Class.forName("m3d19Reflect.Student");
//获取构造方法并使用
//getConstructors()(对象数组)(public构造方法)
//返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造类对象。
Constructor<?>[] cConstructors = c.getConstructors();
//返回所有构造方法(对象数组)
Constructor<?>[] cons = c.getDeclaredConstructors();
//返回一个指定构造函数对象
Constructor<?> c1 = c.getConstructor(String.class,int.class,String.class);
//构造函数实例
Object s = c1.newInstance("张三",2,"abc");
System.out.println(s);
//正常不能对private构造方法创建对象
//暴力反射(通过反射 Constructor方法setAccessible使用私有构造方法创建对象)
Constructor<?> dc1 = c.getDeclaredConstructor(String.class);
dc1.setAccessible(true);//取消访问检查
Object s2 = dc1.newInstance("小王");
System.out.println(s2);

2.4反射获取成员变量

​ 先获取class对象 再用

​ getFields 返回所有pubic成员变量对象数组

​ getDeclareFields 返回所有成员变量对象数组

​ getField 返回指定pubic成员变量对象(参数:成员变量名称(字符串))

​ getDeclareField 返回指定成员变量对象

​ 调用.set方法为对象赋值

​ 成员变量对象.set(对象,值)

Class<?> c = Class.forName("m3d19Reflect.Student");
Field f = c.getField("address");//获取成员变量对象
Field df = c.getDeclaredField("name");//可以获取私有的
df.setAccessible(true);//取消访问检查
Constructor<?> cCon = c.getConstructor();
Object o = cCon.newInstance();//反射创建对象
f.set(o,"西安");//通过反射为对象赋值
System.out.println(o);

2.5反射获取成员方法

​ 先获取class对象 再用

​ getMethods

​ getDeclareMethods

​ getMethod (参数:方法名称(字符串))

​ getDeclareMethod

​ 方法对象.invoke(对象,方法参数)

Class<?> c = Class.forName("m3d19Reflect.Student");
Method[] methods = c.getMethods();//公共方法(包括继承来的)
Method[] declaredMethods = c.getDeclaredMethods();//所有方法 不包含继承的
Method method = c.getMethod("method");
Constructor<?> con = c.getConstructor();
Object o = con.newInstance();
method.invoke(o);//反射使用成员方法

Method method1 = c.getDeclaredMethod("function");
method1.setAccessible(true);//私有方法 取消访问检查
method1.invoke(o);

2.6通过配置文件运行类中的方法

Properties prop = new Properties();
FileReader fr = new FileReader("01\\src\\m3d19Reflect\\class.txt");
prop.load(fr);
fr.close();

String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");

Class<?> c = Class.forName(className);
Method method = c.getMethod(methodName,String.class);

Constructor<?> con = c.getConstructor();
Object o = con.newInstance();
method.invoke(o,"小彭");

注:Properties类的使用

​ Java 语言的配置文件所使用的类

​ 读入:

​ .load(输入流)

​ 以key=value 的 键值对的形式进行存储值。 key值不能重复(继承了hashtable类)

​ 方法.getProperty(key) 返回value

ect o = con.newInstance();
method.invoke(o,“小彭”);




### 注:Properties类的使用

​	Java 语言的配置文件所使用的类

​	读入:

​	.load(输入流)



​	以key=value 的 键值对的形式进行存储值。 key值不能重复(继承了hashtable类)

​	方法.getProperty(key) 返回value

​	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值