Java的反射機制以及使用場景
- 什么是反射
- Class對象
- 如何使用
- 獲取 Class 類對象
- 反射創造對象
- 反射獲取類的構造器
- 反射獲取類的成員變量
- 反射獲取類的方法
- 反射的應用場景
- JDBC 的數據庫的連接
- Spring 框架的使用
什么是反射
Oracle 官方對反射的解釋
Reflection is commonly used by programs which require the ability to examine or
modify the runtime behavior of applications running in the Java virtual machine.
This is a relatively advanced feature and should be used only by developers who
have a strong grasp of the fundamentals of the language. With that caveat in
mind, reflection is a powerful technique and can enable applications to perform
operations which would otherwise be impossible.
Java 的反射機制是指:
- 在運行狀態中,對于任意一個類都能夠知道這個類所有的屬性和方法;
- 并且對于任意一個對象,都能夠調用它的任意一個方法;
- 這種動態獲取信息以及動態調用對象方法的功能成為Java語言的反射機制。
白話解釋
萬物有陰必有陽,有正必有反。既然有反射,就必有“正射”。
那么正射是什么呢?
- 正射
我們在編寫代碼時,當需要使用到某一個類的時候,都會先了解這個類是做什么的。然后實例化這個類,接著用實例化好的對象進行操作,這就是正射。
Student student = new Student();
student.doHomework("數學");
- 反射
反射就是,一開始并不知道我們要初始化的類對象是什么,自然也無法使用 new 關鍵字來創建對象了。
Class clazz = Class.forName("reflection.Student");Method method = clazz.getMethod("doHomework", String.class);Constructor constructor = clazz.getConstructor();Object object = constructor.newInstance();method.invoke(object, "語文");
正射與反射對比
以上兩段代碼,執行效果是一樣的,如圖:
但是,其實現的過程還是有很大的差別的:
第一段代碼在未運行前就已經知道了要運行的類是Student;
第二段代碼則是到整個程序運行的時候,從字符串reflection.Student,才知道要操作的類是Student。
結論
反射就是在運行時才知道要操作的類是什么,并且可以在運行時獲取類的完整構造,并調用對應的方法。
Class對象
要理解Class對象,我們先來了解一下RTTI吧。
RTTI(Run-Time Type Identification)運行時類型識別,其作用是在運行時識別一個對象的類型和類的信息。
Java是如何讓我們在運行時識別對象和類的信息的?主要有兩種方式:
- 一種是傳統的RRTI,它假定我們在編譯期已知道了所有類型。
- 另一種是反射機制,它允許我們在運行時發現和使用類的信息。
每個類都有一個Class對象,每當編譯一個新類就產生一個Class對象(更恰當地說,是被保存在一個同名的.class文件中)。比如創建一個Student類,那么,JVM就會創建一個Student對應Class類的Class對象,該Class對象保存了Student類相關的類型信息。
Class類的對象作用是運行時提供或獲得某個對象的類型信息。
如何使用
獲取 Class 類對象
獲取反射中的Class對象有三種方法。
- 第一種,使用 Class.forName 靜態方法。
Class class1 = Class.forName("reflection.TestReflection");
- 第二種,使用類的.class 方法
Class class2 = TestReflection.class;
- 第三種,使用實例對象的 getClass() 方法。
TestReflection testReflection = new TestReflection();
Class class3 = testReflection.getClass();
反射創造對象
通過反射創造對象,獲取方法,成員變量,構造器
通過反射創建類對象主要有兩種方式:
實例代碼:
//方式一
Class class1 = Class.forName("reflection.Student");
Student student = (Student) class1.newInstance();
System.out.println(student);//方式二
Constructor constructor = class1.getConstructor();
Student student1 = (Student) constructor.newInstance();
System.out.println(student1);
運行結果:
反射獲取類的構造器
反射獲取類的成員變量
反射獲取類的方法
反射的應用場景
反射是Java框架的靈魂技術,很多框架都使用了反射技術,如spring,Mybatis,Hibernate等。
JDBC 的數據庫的連接
在JDBC連接數據庫中,一般包括加載驅動,獲得數據庫連接等步驟。而加載驅動,就是引入相關Jar包后,通過Class.forName() 即反射技術,加載數據庫的驅動程序。
Spring 框架的使用
Spring 通過 XML 配置模式裝載 Bean,也是反射的一個典型例子。
裝載過程:
- 將程序內XML 配置文件加載入內存中
- Java類解析xml里面的內容,得到相關字節碼信息
- 使用反射機制,得到Class實例
- 動態配置實例的屬性,使用
這樣做當然是有好處的:
不用每次都去new實例了,并且可以修改配置文件,比較靈活。