Java中的反射,Java反射
Java反射API
Java反射指的是在運行狀態時,能夠擷取類的屬性和方法或者修改類運行時行為的過程。
java.lang.Class類提供了很多方法用於擷取中繼資料、檢查和改變類運行時的行為。
Java的反射主要涉及java.lang和java.lang.reflect包下的類。
反射應用情境舉例java.lang.Class類
java.lang.Class主要提供了以下兩個功能:
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 |
建立執行個體對象 |
| 4) public boolean isInterface() |
判斷是否是介面 |
| 5) public boolean isArray() |
判斷是否是數組 |
| 6) public boolean isPrimitive() |
判斷是否是未經處理資料類型 |
| 7) public Class getSuperclass() |
返回父類Class引用 |
| 8) public Field[] getDeclaredFields()throws SecurityException |
返回類的成員屬性欄位數組 |
| 9) public Method[] getDeclaredMethods()throws SecurityException |
返回類的方法數組 |
| 10) public Constructor[] getDeclaredConstructors()throws SecurityException |
返回類的構造方法數組 |
| 11) public Method getDeclaredMethod(String name,Class[] parameterTypes)throws NoSuchMethodException,SecurityException |
返回類中指定參數類型的方法 |
怎樣擷取Class對象
有三種方式,如下:
forName()方法樣本
可用於動態載入,當你知道類的全限定名時,可以使用該方式。注意未經處理資料類型不適用該方法;
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()方法樣本:
從執行個體對象中擷取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文法樣本
作用於類名上,也可應用於未經處理資料類型,如下所示:
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對象對應的類型
以下方法可用於判斷Class對象對應的類型:
| 1) public boolean isInterface(): 是否對應介面 |
| 2) public boolean isArray(): 是否對應數組 |
| 3) public boolean isPrimitive(): 是否對應未經處理資料類型 |
程式碼範例:
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通過反射建立執行個體對象
有兩種方式,如下:
所以,通常來講,第二種方式比第一種使用範圍更廣。
Class對象調用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對象調用newInstance()方法樣本
注意這裡可以根據傳入參數的類型來得到指定的構造方法,還可以改變構造方法的存取權限限制。
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,...通過反射調用私人方法
通過反射,我們可以調用其它類的私人方法,主要涉及java.lang.Class和java.lang.reflect.Method類;
其中主要是用到了Method類的setAccessible方法和invoke方法,前者修改存取權限,後者調用方法。
通過調用有參私人方法樣本:
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); }}關於javap工具
使用javap命令可以反組譯碼java的位元組碼檔案,展示class檔案中的欄位屬性、構造方法、普通方法資訊;
使用說明:
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