JAVA安全基础之反射
在JAVA安全中,反射是一个经常使用的技术,所以熟悉使用反射是非常必要的。下面就简单的讲下JAVA的反射的用法
什么是反射
每个类都有对应的Class类对象,该Class类对象包含该类的属性、方法等信息,这个Class类对象就是这个类的反射。
就像镜子一样,一个类照镜子后,镜子里的类对象就是一个Class对象。它描述了这个类的所有属性、方法等。
作用
可以在程序运行过程中,操作这些对象的属性、方法等。
使用
说着其实是挺抽象的,那我们直接通过例子来了解反射
当一个类从JAVA代码到被new出来后,这中间是经历了三个阶段。
![image-20210622121933673](https://i-blog.csdnimg.cn/blog_migrate/165817d1d183cd547020cabd60b1c670.png)
Source源代码阶段:Person.java文件通过JAVAC编译后,成为了Person.class字节码文件,此时两个文件还存在硬盘上,并没有进内存。
Class类对象阶段:把class字节码文件通过类加载器ClassLoader加载进了内存,生成了一个Class类对象,Class类对象把Person.class中的所有属性、方法等都进行了一次封装。
Runtime运行时阶段:也就是new出了一个对象的阶段,此对象参与了程序的运行。
获取Class对象的三种方式
-
Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
-
类名.class:通过类名的属性class获取
-
对象.getClass():getClass()方法在Object类中定义着。
注意:
1)同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
2)因为静态代码块是在类加载的时候执行,所以如果类中包含静态代码块,那么除了Person.class这种方法外的另外两种方法,都会造成静态代码块的执行,且只执行一次。
![image-20210622124149196](https://i-blog.csdnimg.cn/blog_migrate/11b73646e02766ad95a4b4875a1bfbce.png)
获取成员变量
1.获取public 修饰的成员变量
Field[] getFields() :获取所有 public 修饰的成员变量
Field getField(String name) 获取指定名称的 public 修饰的成员变量
2.获取任意的成员变量
Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name) 获取指定名称的的成员变量
获取不是public权限的成员变量需要是要暴力反射
![image-20210622130521536](https://i-blog.csdnimg.cn/blog_migrate/972d93e8f39ef845d5e7fd813a83d55b.png)
获取构造方法
1.获取public 修饰的构造方法
Constructor<?>[] getConstructors() 获取 public 修饰的空参构造方法
Constructor getConstructor(类<?>... parameterTypes) 获取 public 修饰的有参构造方法
2.获取任意的构造方法
Constructor<?>[] getDeclaredConstructors() 无视修饰符获取空参构造方法
Constructor getDeclaredConstructor(类<?>... parameterTypes) 无视修饰符获取有参构造方法
同样要使用暴力反射
![image-20210622131238159](https://i-blog.csdnimg.cn/blog_migrate/0a4ed3d6eff3bbb5df656b4995b3eb33.png)
获取成员方法
1.获取public 修饰的构造方法method
Method[] getMethods() 获取 public 修饰的空参方法method
Method getMethod(String name, 类<?>... parameterTypes) 获取 public 修饰的有参方法method
2.获取任意的method方法
Method[] getDeclaredMethods() 无视修饰符获取空参方法
Method getDeclaredMethod(String name, 类<?>... parameterTypes) 无视修饰符获取有参方法
同样要使用暴力反射
![image-20210622132323320](https://i-blog.csdnimg.cn/blog_migrate/4fa2eb89f11b4043e29f54ee694185b1.png)
获取全类名
String getName()
![image-20210622134105466](https://i-blog.csdnimg.cn/blog_migrate/250092ddfb015003c96d85441b13a21c.png)
反射创建对象的两种方式
一、直接用Class类对象获取对应实例
// 调用无参构造器 ,若是没有,或者类构造函数是私有的,则会报异常
Class clazz = Class.forName("com.yyhuni.Person");
Object o = clazz.newInstance();
二、有带参数的构造函数的类,先获取到其构造对象,再通过该构造方法类获取实例:
Class clazz = Class.forName("com.yyhuni.Person");
//获取构造函数类的对象
Constroctor constroctor = clazz.getConstructor(String.class,Integer.class);
// 使用构造器对象的newInstance方法初始化对象
Object obj = constroctor.newInstance("yy", 18);
欢迎关注我的公众号,同步更新喔
![微信二维码](https://i-blog.csdnimg.cn/blog_migrate/d8604f2af85f8d4cc53cf07210c8b3f1.png)