Java中反射詳解
閱讀目錄
- Java反射API
- 通過反射創(chuàng)建實(shí)例對象
- 通過反射調(diào)用私有方法
- 關(guān)于javap工具
- 參考資料
Java反射API
Java反射指的是在運(yùn)行狀態(tài)時,能夠獲取類的屬性和方法或者修改類運(yùn)行時行為的過程。
java.lang.Class類提供了很多方法用于獲取元數(shù)據(jù)、檢查和改變類運(yùn)行時的行為。
Java的反射主要涉及java.lang和java.lang.reflect包下的類。
反射應(yīng)用場景舉例
- IDE, 如Eclipse、MyEclipse、NetBeans等;
- 調(diào)試器;
- 測試工具等;
- 各大框架、spring、hibernate等;
java.lang.Class類
java.lang.Class主要提供了以下兩個功能:
- 提供方法用于訪問運(yùn)行期間類的元數(shù)據(jù);
- 提供方法用于檢查和修改類的運(yùn)行時行為;
java.lang.Class類常用方法
Method | Description |
---|---|
1) public String getName() | 返回類名 |
2) public static Class forName(String className)throws ClassNotFoundException | 加載類并返回Class對象 |
3) public Object newInstance()throws InstantiationException,IllegalAccessException | 創(chuàng)建實(shí)例對象 |
4) public boolean isInterface() | 判斷是否是接口 |
5) public boolean isArray() | 判斷是否是數(shù)組 |
6) public boolean isPrimitive() | 判斷是否是原始數(shù)據(jù)類型 |
7) public Class getSuperclass() | 返回父類Class引用 |
8) public Field[] getDeclaredFields()throws SecurityException | 返回類的成員屬性字段數(shù)組 |
9) public Method[] getDeclaredMethods()throws SecurityException | 返回類的方法數(shù)組 |
10) public Constructor[] getDeclaredConstructors()throws SecurityException | 返回類的構(gòu)造方法數(shù)組 |
11) public Method getDeclaredMethod(String name,Class[] parameterTypes)throws NoSuchMethodException,SecurityException | 返回類中指定參數(shù)類型的方法 |
怎樣獲取Class對象
有三種方式,如下:
- Class類的forName()方法,動態(tài)加載,運(yùn)行時,開始裝入類, 并做類的靜態(tài)初始化
- 對象的getClass()方法,靜態(tài)加載(編譯時已加載)
- .class語法, 靜態(tài)加載(編譯時已加載)
forName()方法示例
可用于動態(tài)加載,當(dāng)你知道類的全限定名時,可以使用該方式。注意原始數(shù)據(jù)類型不適用該方法;
package tmp; class Simple { } public class Test { public static void main(String args[]) throws ClassNotFoundException { Class<?> c = Class.forName("tmp.Simple"); System.out.println(c.getName()); System.out.println(c.getSimpleName()); } }
tmp.Simple Simple
getClass()方法示例:
從實(shí)例對象中獲取Class對象
package tmp; class Simple { } public class Test { void printName(Object obj) { } public static void main(String args[]) { Simple s = new Simple(); Class<? extends Object> c = s.getClass(); System.out.println(c.getName()); System.out.println(c.getSimpleName()); } }
tmp.Simple Simple
.class語法示例
作用于類名上,也可應(yīng)用于原始數(shù)據(jù)類型,如下所示:
package tmp; public class Test { public static void main(String args[]) { Class<Boolean> c = boolean.class; System.out.println(c.getName()); Class<Test> c2 = Test.class; System.out.println(c2.getName()); } }
boolean tmp.Test
判斷Class對象對應(yīng)的類型
以下方法可用于判斷Class對象對應(yīng)的類型:
1) public boolean isInterface(): 是否對應(yīng)接口 |
2) public boolean isArray(): 是否對應(yīng)數(shù)組 |
3) public boolean isPrimitive(): 是否對應(yīng)原始數(shù)據(jù)類型 |
代碼示例:
package tmp; class Simple { } interface My { } public class Test { public static void main(String args[]) { try { Class<?> c = Class.forName("tmp.Simple"); System.out.println(c.isInterface()); Class<?> c2 = Class.forName("tmp.My"); System.out.println(c2.isInterface()); } catch (Exception e) { System.out.println(e); } } }
false true
通過反射創(chuàng)建實(shí)例對象
有兩種方式,如下:
- 通過Class對象的newInstance()方法創(chuàng)建,這種方式只能調(diào)用無參構(gòu)造方法;
- 通過Constructor對象的newInstance()方法創(chuàng)建,這種方式適用于有參構(gòu)造方法,并且還可以破壞單例模式,調(diào)用私有構(gòu)造方法;
所以,通常來講,第二種方式比第一種使用范圍更廣。
Class對象調(diào)用newInstance()方法示例
package tmp; class Simple { void message() { System.out.println("Hello Java"); } } public class Test { public static void main(String args[]) { try { Class<?> c = Class.forName("tmp.Simple"); Simple s = (Simple) c.newInstance(); s.message(); } catch (Exception e) { System.out.println(e); } } }
Hello Java
Constructor對象調(diào)用newInstance()方法示例
注意這里可以根據(jù)傳入?yún)?shù)的類型來得到指定的構(gòu)造方法,還可以改變構(gòu)造方法的訪問權(quán)限限制。
package tmp; import java.lang.reflect.Constructor; class Simple { private String msg; void message() { System.out.println("Hello Java," + msg); } private Simple(String s){ this.msg = s; } } public class Test { public static void main(String args[]) { try { Class<?> c = Class.forName("tmp.Simple"); Constructor<?> con = c.getDeclaredConstructor(String.class); con.setAccessible(true); Simple s = (Simple) con.newInstance("..."); s.message(); } catch (Exception e) { System.out.println(e); } } }
Hello Java,...
通過反射調(diào)用私有方法
通過反射,我們可以調(diào)用其它類的私有方法,主要涉及java.lang.Class和java.lang.reflect.Method類;
其中主要是用到了Method類的setAccessible方法和invoke方法,前者修改訪問權(quán)限,后者調(diào)用方法。
通過調(diào)用有參私有方法示例:
package tmp; import java.lang.reflect.Method; class A { private void cube(int n) { System.out.println(n * n * n); } } class Test { public static void main(String args[]) throws Exception { Class<A> c = A.class; Object obj = c.newInstance(); Method m = c.getDeclaredMethod("cube", new Class[]{ int.class }); m.setAccessible(true); m.invoke(obj, 4); } }
關(guān)于javap工具
使用javap命令可以反匯編java的字節(jié)碼文件,展示class文件中的字段屬性、構(gòu)造方法、普通方法信息;
使用說明:
javap java.lang.Object示例
javap -c Test示例:
寫個簡單的Test類,如下:
package tmp; class Simple { } public class Test { public static void main(String args[]) { System.out.println("Hello"); } }
輸入javap -c Test:
參考資料
基本屬于翻譯,做了小部分修改
http://www.javatpoint.com/java-reflection
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!
相關(guān)文章
手把手教學(xué)Win10同時安裝兩個版本的JDK并隨時切換(JDK8和JDK11)
最近在學(xué)習(xí)JDK11的一些新特性,但是日常使用基本上都是基于JDK8,因此,需要在win環(huán)境下安裝多個版本的JDK,下面這篇文章主要給大家介紹了手把手教學(xué)Win10同時安裝兩個版本的JDK(JDK8和JDK11)并隨時切換的相關(guān)資料,需要的朋友可以參考下2023-03-03Java方法參數(shù)傳遞如何實(shí)現(xiàn)
這篇文章主要介紹了Java方法參數(shù)傳遞如何實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-05-05IntelliJ IDEA(2019)之mybatis反向生成的實(shí)現(xiàn)
這篇文章主要介紹了IntelliJ IDEA(2019)之mybatis反向生成,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10SpringBoot--Banner的定制和關(guān)閉操作
這篇文章主要介紹了SpringBoot--Banner的定制和關(guān)閉操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2018-05-05詳解Java前綴樹Trie的原理及代碼實(shí)現(xiàn)
Trie又被稱為前綴樹、字典樹。Trie利用字符串的公共前綴來高效地存儲和檢索字符串?dāng)?shù)據(jù)集中的關(guān)鍵詞,最大限度地減少無謂的字符串比較,其核心思想是用空間換時間。本文主要介紹了Trie的原理及實(shí)現(xiàn),感興趣的可以了解一下2022-11-11SpringBoot結(jié)合Tess4J實(shí)現(xiàn)拍圖識字的示例代碼
圖片中的文字提取已經(jīng)越來越多地應(yīng)用于數(shù)據(jù)輸入和自動化處理過程,本文主要介紹了SpringBoot結(jié)合Tess4J實(shí)現(xiàn)拍圖識字的示例代碼,具有一定的參考價值,感興趣的可以了解一下2024-06-06Spring Data JPA例子代碼[基于Spring Boot、Mysql]
這篇文章主要介紹了Spring Data JPA例子代碼[基于Spring Boot、Mysql],小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04解決@PathVariable參數(shù)接收不完整的問題
這篇文章主要介紹了解決@PathVariable參數(shù)接收不完整的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08