JAVA核心技術學習筆記--反射
反射
反射庫(reflection library)提供了一個非常豐富且精心設計的工具集,以便編寫能夠動態操縱Java程式碼的程式。
使用反射,能在設計或者在新增新類的時候,能夠快速應用開發工具動態的查詢新新增類的能力。
能夠分析類能力的程式稱為 反射 反射功能極其強大可以用來
在執行時分析類的能力
在執行時檢視物件
實現通用的陣列來操作程式碼
利用Method物件,此物件很類似C++中的函式指標
1,前提介紹: Class 類
在程式執行期間,Java執行時系統始終為所有物件維護一個被稱為執行時的型別標識,這個資訊跟蹤著每個物件專屬的類。
Class類就是用來專門儲存這些類的資訊,透過Object類中的getClass()方法得到每個類的Class類例項
Person p; Class cl = p.getClass();
一個Class類可以用來儲存一個類的屬性,如:
p.setName("ZhangSan");System.out.print(cl.getName()+" "+p.getName());
此時程式會輸出
Person ZhangSan
Class的getName()方法可以得到這個類的類名。
獲得類的Class例項的第2種方法:Class.forName(類名)
String className = "com.henu.Person"; Class cl = Class.forName(className);
第三種方法,直接 類名.class
Class class1 = Person.class; Class class2 = Random.class;
透過獲得的Class例項再建立類的例項
Class cl = p.getClass(); Perons p = cl.newInstance();
以上程式碼在使用時要放在try catch程式碼塊裡,來處理捕獲的異常
2,利用反射分析類的能力,檢查類的結構
java.lang.reflect包中有三個類
Field 描述類的域 getType()方法可以返回描述域所屬型別的Class物件
Method 描述類的方法
Constructor 描述類的構造器
這三個類都有一個getModifiers的方法,描述各自的訪問修飾符,public private final...等,
再透過Modifier類中的isPublic,isPrivate,isXxx方法對其進行判斷.
getFields
getMethods
getConstructors
這三個方法分別返回類提供的public域,方法,構造器陣列,其中包括超類的共有成員.getDeclareFields
getDeclareMethods
getDeclaredConstructors
這三個方法將返回類中宣告的全部域,方法和構造器,包括private,protect,但不包括超類的共有成員
在執行時使用反射分析物件
接下來進一步檢視資料域的實際內容給
Person p = new Person("張三",20); Class cl = p.getClass(); Field name = cl.getDeclaredField("name");//獲得Person 類的name域;Object value = name.get(p); // 此時value = "張三"
值的注意的一點是,若name域在Person類中是私有的,程式碼會丟擲異常,我們需要對獲得的資料域進行設定
Person p = new Person("張三",20); Class cl = p.getClass(); Field name = cl.getDeclaredField("name");//獲得Person 類的name域;name.setAccessible(true);Object value = name.get(p); // 此時value = "張三"
setAccessible方法是AccessibleObject類中的一個方法,它是Field,Method,Constructor類的共有超類,是為了除錯,持久儲存和相似除錯提供的.
若資料域是基本資料型別,可以使用域.getDouble(類的例項),getInt(類的例項),也可以繼續使用get( )方法,反射機制會自動的將這個域值裝箱,變成Double,Integer。
.set(obj,value)方法可以將obj物件的指定域進行賦值
name.set(p,"李四")//此時p物件的name為李四
3,使用反射編寫泛型陣列程式碼
java.lang.reflect包中的Array類允許動態的建立陣列
以前我們學過Arrays類中有個copyOf()方法,可以用來擴充已經滿了的陣列.
Person[ ] team = new Person[10]; team = Arrays.copyOf(team,2*team.length);
我們可以用反射寫一個通用的擴充陣列長度的方法,能擴充任意型別的陣列。
首先我們寫一個錯誤的例子
public static Object[] badCopyOf(Object[] a,int newLength) { Object[] newArray = new Object[newLength]; System.arrayCopy(a,0,newArray,0,Math.min(a.length,newLength));//第四個引數是要從原陣列複製元素的個數 return newArray; }
為什麼這個程式碼是錯的呢,因為這個函式返回的陣列型別是物件陣列型別(Object [])
一個物件陣列不能轉化成特定的類的陣列(Object[]->person[]),這樣做會產生異常,其實,當我們把Person[]轉化成 Object[] 再轉化成Person[]是可以的,但是一個一開始就是Object[]的陣列是不能轉的,我們可以透過下面這個方法
Object newArray = Array.newInstance(componentType,int newLength);
java.lang.reflect.Array中的靜態方法newInstance方法能夠構造新的陣列,第一個引數是元素的型別,第二個是陣列長度。所以現在我們需要獲得新陣列的元素型別和陣列長度。
獲得陣列的長度可以透過.getLength()或者Array.getLength(陣列)獲得
獲得陣列的元素型別可以透過Class類的getComponentType()獲得
所以我們現在要實現一個通用的擴充任意型別的方法要經過3步
首先獲得陣列的Class物件
確認它是一個陣列型別(透過Class類的isArray()方法)
使用Class類的getComponentType()方法確定陣列的型別
public static Object goodCopyOf(Object a,int newLength) { Class cl = p.getClass(); if (cl.isArray()) return null;//如果不是陣列型別就結束 Class componentType = cl.getComponentType();//獲得陣列的元素型別 int length = a.getLength(); Object newArray = Array.newInstance(componentType,length); System.arrayCopy(a,0,newArray,0,Math.min(length,newLength)); return newArray; }
這樣這個方法就可以用了來擴充任意型別的陣列了
int[] a = {1,2,3,4,5}; a = (int [])goodCopyOf(a,10);
透過Method的invoke方法呼叫類的任意方法
兩個方法
Method method = Person.getClass().getMethod(方法名,方法的引數型別.class)
method.invoke(方法隸屬的類的例項,方法的引數值)
//動態構造InvokeTest類的例項Class<?> classType = InvokeTest.class;Object invokeTest = classType.newInstance();//動態構造InvokeTest類的add(int num1, int num2)方法,標記為addMethod的Method物件Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});//動態構造的Method物件invoke委託動態構造的InvokeTest物件,執行對應形參的add方法Object result = addMethod.invoke(invokeTest, new Object[]{1, 2});
作者:Limmerence
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3349/viewspace-2816815/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java學習筆記系列-反射Java筆記反射
- 《Java核心技術》第五章 繼承 學習筆記Java繼承筆記
- java核心技術閱讀筆記Java筆記
- Java核心技術筆記 繼承Java筆記繼承
- Java註解與反射學習筆記Java反射筆記
- 《Java核心技術 卷I》學習筆記10:使用預定義類Java筆記
- java核心技術筆記--執行緒Java筆記執行緒
- java反射之動態代理學習筆記Java反射筆記
- 《Java核心技術 卷I》學習筆記2:資料型別、變數與常量Java筆記資料型別變數
- JAVA學習筆記—JAVA WEB(二)JAVA WEB核心(下)Java筆記Web
- java反射技術Java反射
- Java筆記-反射Java筆記反射
- Java核心技術筆記 異常、斷言和日誌Java筆記
- 註解和反射學習筆記反射筆記
- Java核心技術梳理-類載入機制與反射Java反射
- JVM核心學習筆記JVM筆記
- Java筆記-Java反射(二)Java筆記反射
- Java核心技術 卷1 基礎知識 部分筆記Java筆記
- 【Java 反射學習】Java 反射基礎Java反射
- [Java 反射學習] Java 反射基礎Java反射
- java核心技術卷1學習思維導圖Java
- LLM學習筆記-長度外推技術筆記
- Java程式設計思想學習筆記4 - 序列化技術Java程式設計筆記
- Android 學習筆記核心篇Android筆記
- Java學習_反射Java反射
- Java學習:反射Java反射
- Redis核心技術筆記16-20Redis筆記
- Redis核心技術筆記21-25Redis筆記
- Redis核心技術筆記05-06Redis筆記
- Redis核心技術筆記07-08Redis筆記
- Redis核心技術筆記11-15Redis筆記
- Redis核心技術筆記01-02Redis筆記
- Redis核心技術筆記03-04Redis筆記
- Go語言核心36講(Go語言進階技術一)--學習筆記Go筆記
- Go語言核心36講(Go語言進階技術十四)--學習筆記Go筆記
- Go語言核心36講(Go語言進階技術九)--學習筆記Go筆記
- Go語言核心36講(Go語言進階技術十)--學習筆記Go筆記
- Go語言核心36講(Go語言進階技術十一)--學習筆記Go筆記