反射是框架设计的灵魂
(前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))
一、反射的概述
1.正:一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作
Student student = new Student(); //直接初始化,「正」
student.setAge(19);
2.反射
2.1为什么要反射:
一开始并不知道我要初始化的类对象是什么,也无法使用 new 关键字来创建对象,这时候,我们使用 JDK 提供的反射 API 进行反射调用
2.2什么是反射:
反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
2.3JAVA反射机制:
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
二:反射常用API
3.1 获取反射中的Class对象
在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的 Class 对象。获取方法如下:
1.知道该类的全路径名时,使用 Class.forName(“类的全限定名”) 静态方法。 全限定名 = 包名 + 类名
2.使用 .class 方法。
3.使用类对象的 getClass() 方法。
3.2 通过反射创建类对象
3.2.1:通过 Class 对象的 newInstance() 方法。
Class tao = student.class;
Student student= (Student )clz.newInstance();
3.2.2:通过 Constructor 对象的 newInstance() 方法
Class tao = Student.class;
Constructor constructor = tao.getConstructor();
Student student = (Student)constructor.newInstance();
上面两种方式的区别:通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。
3.3 通过反射获取类属性、方法、构造器
通过 Class 对象的 getFields() 方法可以获取 Class 类的属性,但无法获取私有属性。
使用 Class 对象的 getDeclaredFields() 方法则可以获取包括私有属性在内的所有属性
与获取类属性一样,当我们去获取类方法、类构造器时,如果要获取私有方法或私有构造器,则必须使用有 declared 关键字的方法。
4.反射应用场景
4.1:做基础框架
典型的除了Hibernate之外,还有Spring也用到很多反射机制。经典的就是在xml文件或者properties里面写好了配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射机制,根据这个字符串获得某个类的Class实例,这样就可以动态配置一些东西,不用每一次都要在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护起来就很方便了,同时有时候要适应某些需求,Java类里面不一定能直接调用另外的方法,这时候也可以通过反射机制来实现。
4.2做一个可以安装插件功能的软件
不知道插件的类型名称,无法实例化对象,无法在代码中 New出来 ,但反射可以,通过反射,动态加载程序集,然后读出类,检查标记之后再实例化对象,就可以获得正确的类实例。
4.3:在编码阶段不知道那个类名,要在运行期从配置文件读取类名, 这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象.反射的目的就是为了扩展未知的应用。
很多工厂模式就是使用的反射。
5 性能分析
反射机制是一种程序自我分析的能力。用于获取一个类的类变量,构造函数,方法,修饰符。
优点:运行期类型的判断,动态类加载,动态代理使用反射。
缺点:性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。