Java反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
有些情况下,我们要使用的类在运行时才会确定,这个时候我们不能在编译期就使用它,因此只能通过反射的形式来使用在运行时才存在的类,这是反射用得比较多的场景。
假如有两个程序员A、B,程序员A 在写程序的时候,需要使用程序员B 所写的类,但程序员 B并没完成他所写的类。那么程序员A的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让程序员A在没有得到程序员B 所写的类的时候,来完成自身代码的编译。
Java反射可以访问和修改私有成员变量
-
1、基本反射技术
根据一个字符串得到一个类
(1)getClass 方法
(2)Class.forName(getSuperclass可以获取父类)
-
2、获取类的成员
当类中方法定义为私有的时候我们能调用?不能!当变量是私有的时候我们能获取吗?不能!但是反射可以,比如源码中有你需要用到的方法,但是那个方法是私有的,这个时候你就可以通过反射去执行这个私有方法,并且获取私有变量。
为了便于测试,我们定义一个Test类,Test类如下:(省略get和set方法)。Test类中我们定义是三个私有变量,生成两个公有的含参构造方法和一个私有的含参构造方法以及一个公有的无参构造方法。
![image-20210811092503753](https://i-blog.csdnimg.cn/blog_migrate/bddb098df55be6ebdb51e9f7a80591df.png)
下面我们通过反射获取这些构造方法
(1)获取类的所有构造方法
通过getDeclaredConstructors可以返回类的所有构造方法,返回的是一个数组因为构造方法可能不止一个,通过getModifiers可以得到构造方法的类型,getParameterTypes可以得到构造方法的所有参数,返回的是一个Class数组,所以如果想获取所有构造方法以及每个构造方法的参数类型、代码如下:
![image-20210811093721044](https://i-blog.csdnimg.cn/blog_migrate/3669af8a197e8bc8e6d249d56768a169.png)
(2)获取类中的特定构造方法
可以通过getConstructors方法获取类中 所有的public类型的构造方法,代码只需改动一行
constructors = c4.getConstructors();
可以通过getDeclaredConstructor()方法传参获取特定参数类型的构造方法,这里注意是getDeclaredConstructor()不是 getDeclaredConstructors() ,所以返回的是一个Class对象而不是一个Class数组。
获取无参构造方法直接不传参数,如下所示:
(3)调用构造方法
从这里开始慢慢到了关键的一步。得到类的实例,主要借助于newInstance方法,调用私有构造方法,需要要设置constructors.setAccessible(true);
代码如下:
![image-20210811094843805](https://i-blog.csdnimg.cn/blog_migrate/1e21aa298734b86509ad46bf50efe3d6.png)
(4)调用类的私有方法
如何调用类中的私有方法呢?先在Test测试类中编写一个测试的私有方法,然后通过 getDeclaredMethod方法获取到这个私有方法,第一个参数是方法名,第二个参数是参数类型,然后通过invoke方法执行,invoke需要两个参数一个是类的实例,一个是方法参数。
![image-20210811095123818](https://i-blog.csdnimg.cn/blog_migrate/e6604492f23cdbf36bef7bbeeff6a1b2.png)
![image-20210811095245376](https://i-blog.csdnimg.cn/blog_migrate/0fe01c7c2d8e9b671348e9be3fdf626a.png)
(5)获取类的私有字段并修改值
修改Test类的私有字段name的值只对当前的实例对象有效。先在Test 测试类中给私有字段赋值,并重写一个测试的toString方法输出私有字段name。然后通过getDeclaredField 方法获取私有字段name,通过set方法修改私有字段name,最后调用方法toString 输出修改后的私有字段name。
![image-20210811100120942](https://i-blog.csdnimg.cn/blog_migrate/89fc4bcba8d454c217e652a1484c3d1b.png)
(6)利用反射执行代码
以java.lang.Runtime类为例,执行getRuntime.exec(“cale.exe”)方法,弹出计算器,代码如下:
![image-20210811100947100](https://i-blog.csdnimg.cn/blog_migrate/6c1a5c38506bc3c03c099cd55549bc9a.png)