提示:该文章主要根据b站韩顺平老师的视频学习而来
前言
前面我们大致了解了什么是java的反射机制。本篇文章我将继续就Java反射机制进行学习。希望能帮助帮助到我自己和阅读者。
一、反射的原理是什么?
反射的原理:在进行类加载的时候,在堆中生成一个记录类结构的Class对象。
二、主要内容
1.相关类
Class:代表一个类,Class对象表示某个类加载后在堆中的对象。
Field:代表类的成员变量,Field对象表示某个类的成员变量。
Method:代表类的方法,Method对象表示某个类的方法。
Constructor:代表类的构造器,Constructor对象代表某个类的构造器。
它们都在java.lang.reflection
2.反射的优缺点
优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活。如果没有反射机制,框架技术也就失去了底层支撑。
缺点:使用反射基本是解释执行,对代码的执行速度有影响。但是这个影响可以调优,即可以使用关闭访问检查的方法——setAccessible()。Method、Field、Constructor都有setAccessible()方法。传入方法的参数值为boolean类型,true为取消检查,反之为开启。调优之后执行速度会有提升,但是提升不大。
3.深入理解Class类
对于Class类,我们需要知道以下几点:
1.Class也是类,因此也继承Object类。
2.Class对象不是new出来的,而是系统创建的。
3.对于某个类的Class对象,在内存中只存在一份,因为类只加载一次。
4.每个类的实例都会记得自己是哪个Class实例所生成的。
5.通过Class对象可以完整的得到一个类的完整结构(即使是类的私有属性,我们也可以使用反射暴破的方式得到类的完整结构),通过一系列的API。
6.Class对象是存放在堆中的,而类的字节码二进制文件(即.class文件,也称元数据)是放在方法区的。
Class类的一些常用方法:
哪些类具有Class类对象:
如何获取Class类的对象:
我们分为6种情况:
1.已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()来获取。可能会抛出ClassNotFoundException,实例:Class c1 = Class.forName("类的全类名");
应用场景:多用于配置文件,读取类的全路径,加载类。
2.若已知具体类,通过类的class获取,该方法最为安全可靠,程序性能也最好。实例:Class c2 =
Cat.class;
应用场景:多用于参数传递,比如通过反射得到对应构造器对象。
3.已知某个类的实例,调用该实例的getClass()方法获取Class对象,实例:Class c3 = 实例.getClass();
应用场景:创建好的对象获取Class。
4.其他方式:
ClassLoader cl = 对象.getClass().getClassLoader();
Class c4 = cl.loadClass("类的全类名");
5.基本数据类型:
class c5 = 基本数据类型.class;
6.基本数据类型对应包装类:
Class c6 = 包装类.TYPE;
4.jvm类加载的过程
深入了解可以看这篇优质文章:
这里暂不作深入了解,学jvm的时候再深入了解。
5.如何通过反射查看类的结构
使用Java.lang.Class
使用Java.lang.reflect.FIeid
使用Java.lang.reflect.Method
使用Java.lang.reflect.Constuctor
6.通过反射创建对象和访问类中成员
通过反射创建对象:
1.调用对象的无参构造器newInstance()。
2.调用对象的指定Public构造器getConstructor(String.class),参数是参数类型对应的Class对象。
3.调用对象指定的所有构造器getDeclaredConstructor(String.class)。
4.针对与private使用setAccessible()暴破。
先使用3的方法得到私有的构造器,然后调用其setAccessible()方法(暴破),之后我们就可以访问私有的构造器。反射面前, 都是纸老虎。
例:
Constructor constructor = Class对象.getDeclareConstructor(Class c);
constructor.setAccessible(true);
object o = constructor.newInstance(Class c);
通过反射访问类中成员:
Field对象:
Field f = Class对象.getDeclaredField(属性名);
//如果是私有属性 我们则需要暴破
f.setAccessible();
f.set(对象,值);//赋值
f.get(对象);//得到值
Method对象:
Method m = Class对象.getDeclaredMethod(方法名,方法的参数类型的Class对象);
//得到对象实例来调用方法
Object o = Class对象.newInstance();
//如果方法是私有的,一样需要暴破
m.setAccessible();
//调用方法
m.invoke(o,方法参数);
总结
以上就是本人结合韩老师的视频总结来的一些Java反射的知识点,个人觉得韩老师的课还是非常的详细。最后再放上韩老师给的两道练习题。