【Java】Java反射机制重点总结
文章目錄
- Java Reflection
- Java反射機制提供的功能
- Java反射相關的主要API
- java.lang.Class類
- Class類的核心要點
- Class類的重要API
- 實例
- 實例化Class類對象(四種方法)
- 創建類對象并獲取類的完整結構
- 獲取Class對象后創建類的對象
- 通過反射調用類的完整結構
- 獲取實現的全部接口
- 獲取所繼承的父類
- 獲取全部的構造器
- 獲取全部的方法
- 獲取全部的屬性
- 獲取Annotation相關
- 獲取泛型相關
- 獲取類所在的包
- 調用指定方法
- 調用指定屬性
- 總結說明
Java Reflection
Reflection(反射)是被視為動態語言的關鍵,反射機制 允許程序在執行期借助于Reflection API取得任何類的內部信息,并能直接操作任意對象的內部屬性及方法。
Java反射機制提供的功能
- 在運行時判斷任意一個對象所屬的類
- 在運行時構造任意一個類的對象
- 在運行時判斷任意一個類所具有的成員變量和方法
- 在運行時調用任意一個對象的成員變量和方法
- 生成動態代理
- ……
Java反射相關的主要API
- java.lang.Class:代表一個類
- java.lang.reflect.Method:代表類的方法
- java.lang.reflect.Field:代表類的成員變量
- java.lang.reflect.Constructor:代表類的構造方法
- …
java.lang.Class類
在Object類中定義了public final Class getClass(),此方法將被所有子類繼承(要注意Object是所有類的父類)。
該方法返回值的類型是一個Class類,此類是Java反射的源頭。
實際上所謂反射從程序的運行結果來看也很好理解:通過對象反射求出類的名稱。
Class類的核心要點
反射后可以得到某個類的以下信息:屬性、方法、構造器、實現的接口
對于每個類而言,JRE 都為其保留一個不變的 Class 類型的對象。
下面的內容要記住:
- 一個 Class 對象包含了特定某個類的有關信息
- Class本身也是一個類
- Class 對象只能由系統建立對象
- 一個類在 JVM 中只會有一個Class實例
- 一個Class對象對應的是一個加載到JVM中的一個.class文件
- 每個類的實例都會記得自己是由哪個 Class 實例所生成
- 通過Class可以完整地得到一個類中的完整結構
- ……
Class類的重要API
| static Class forName(String name) | 返回指定類名 name 的 Class 對象 |
| Object newInstance() | 調用缺省構造函數,返回該Class對象的一個實例 |
| String getName() | 返回此Class對象所表示的實體(類、接口、數組類、基 本類型或void)名稱 |
| Class getSuperClass() | 返回當前Class對象的父類的Class對象 |
| Class[] getInterfaces() | 獲取當前Class對象的接口 |
| ClassLoader getClassLoader() | 返回該類的類加載器 |
| Class getSuperclass() | 返回表示此Class所表示的實體的超類的Class |
| Constructor[] getConstructors() | 返回一個包含某些Constructor對象的數組 |
| Field[] getDeclaredFields() | 返回Field對象的一個數組 |
| Method getMethod(String name,Class … paramTypes) | 返回一個Method對象,此對象的形參類型為paramType |
實例
String str = "Person"; Class clazz = Class.forName(str); Object obj = clazz.newInstance(); Field field = clazz.getField("name"); field.set(obj, "Peter"); Object obj2 = field.get(obj); System. out.println (obj2);實例化Class類對象(四種方法)
方法一:
前提:若已知具體的類,通過類的class屬性獲取,該方法最為安全可靠,程序性能最高
實例:
方法二:
前提:已知某個類的實例,調用該實例的getClass()方法獲取Class對象
實例:
方法三:
前提:已知一個類的全類名,且該類在類路徑下,可通過Class類的靜態方法forName()獲取,可能拋出 ClassNotFoundException
實例:
方法四:
實例:
創建類對象并獲取類的完整結構
獲取Class對象后創建類的對象
可以調用Class對象的newInstance()方法就可以啦,但也有以下要求:
- 類必須有一個無參數的構造器
- 類的構造器的訪問權限需要足夠
而有的類不具有無參數構造器,但只要在操作的時候明確的調用類中的構造方法,并將參數傳遞進去之后,也可以實例化操作。
步驟如下:
實例:
//1.根據全類名獲取對應的Class對象 String name = "Person"; Class clazz = Class.forName(name); //2.調用指定參數結構的構造器,生成Constructor的實例 Constructor constructor = clazz.getConstructor(String.class,Integer.class); //3.通過Constructor的實例創建對應類的對象,并初始化類屬性 Person person = (Person)constructor.newInstance("Peter", 100); System.out.println(person);通過反射調用類的完整結構
獲取 Interface、Superclass、Constructor、Method、Field、Annotation、ParameterizedType、Package 相關!
獲取實現的全部接口
- public Class<?>[] getInterfaces():確定此對象所表示的類或接口實現的接口
獲取所繼承的父類
- public Class<? Super T> getSuperclass():返回表示此 Class 所表示的實體(類、接口、基本類 型)的父類的 Class
獲取全部的構造器
- public Constructor[] getConstructors():返回此 Class 對象所表示的類的所有public構造方法
- public Constructor[] getDeclaredConstructors():返回此 Class 對象表示的類聲明的所有構造方法
Constructor類中:
- 取得修飾符:public int getModifiers();
- 取得方法名稱:public String getName();
- 取得參數的類型:public Class<?>[] getParameterTypes();
獲取全部的方法
- public Method[] getDeclaredMethods():返回此Class對象所表示的類或接口的全部方法
- public Method[] getMethods():返回此Class對象所表示的類或接口的public的方法
Method類中:
- public Class<?> getReturnType():取得全部的返回值
- public Class<?>[] getParameterTypes():取得全部的參數
- public int getModifiers():取得修飾符
- public Class<?>[] getExceptionTypes():取得異常信息
獲取全部的屬性
- public Field[] getFields():返回此Class對象所表示的類或接口的public的Field
- public Field[] getDeclaredFields():返回此Class對象所表示的類或接口的全部Field
Field方法中:
- public int getModifiers():以整數形式返回此Field的修飾符
- public Class<?> getType():得到Field的屬性類型 ? public String getName() 返回Field的名稱
獲取Annotation相關
- get Annotation(Class annotationClass)
- getDeclaredAnnotations()
獲取泛型相關
- 獲取父類泛型類型:Type getGenericSuperclass()
- 泛型類型:ParameterizedType
- 獲取實際的泛型類型參數數組:getActualTypeArguments()
獲取類所在的包
- Package getPackage()
調用指定方法
通過反射,調用類中的方法,通過Method類完成。步驟:
對Object invoke(Object obj, Object … args)的說明:
- Object 對應原方法的返回值,若原方法無返回值,此時 返回null
- 若原方法若為靜態方法,此時形參Object obj可為null
- 若原方法形參列表為空,則Object[] args為null
- 若原方法聲明為private,則需要在調用此invoke()方法前, 顯式調用方法對象的setAccessible(true)方法,將可訪問private的方法
調用指定屬性
在反射機制中,可以直接通過Field類操作類中的屬性,通過Field類提供的set() 和get()方法就可以完成設置和取得屬性內容的操作。
- public Field getField(String name):返回此Class對象表示的類或接口的指定的 public的Field。
- public Field getDeclaredField(String name):返回此Class對象表示的類或接口的 指定的Field。
在Field中:
- public Object get(Object obj):取得指定對象obj上此Field的屬性內容
- public void set(Object obj,Object value):設置指定對象obj上此Field的屬性內容
注:在類中屬性都設置為private的前提下,在使用set()和get()方法時,首先要 使用Field類中的setAccessible(true)方法將需要操作的屬性設置為可以被外部訪 問。
- public void setAccessible(true)訪問私有屬性時,讓這個屬性可見
總結說明
- 在實際的操作中,取得類的信息的操作代碼,并不會經常開發
- 一定要熟悉java.lang.reflect包的作用,反射機制
- 學會如何取得屬性、方法、構造器的名稱,修飾符等
Java其實是一種強類型的靜態語言,編譯成.class后在JVM中解釋執行。Java的反射機制和動態代理則為之提供了一種運行時的“動態性”,彌補了Java靜態性的不足。
對于初學者,倒可不必急于深挖Java的反射機制,但在JavaSE初學的后期建議還是掌握一下反射的知識,特別是一些思想,這對深入理解框架有很重要。
反射的重要性不在于普普通通的JavaSE開發(事實上也沒見誰閑的沒事寫個JavaSE程序還非要用大量反射內容),在于未來,加油,
總結
以上是生活随笔為你收集整理的【Java】Java反射机制重点总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Servlet】Servlet声明配置
- 下一篇: 麦森数(洛谷P1045题题解,Java语