JAVA反射學習筆記
阿新 • • 發佈:2019-01-22
目錄
一、Class類的使用與動態載入類
package com.study.reflect; /** * 類功能描述:Class類的使用 * * @author:*** * @createTime:2018/11/12 16:33 */ public class Demo { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { //任何一個類都是Class的例項物件,這個例項物件有三種表達方式 c1==c2==c3 //c1 c2 c3 是DemoA的類型別(class type) DemoA demoA = new DemoA(); Class c1 = demoA.getClass(); Class c2 = DemoA.class; //Class.forName動態載入類(執行時載入類) new是靜態載入類(編譯時載入類) Class c3 = Class.forName("com.study.reflect.DemoA"); System.out.println(c1 == c2 && c2 == c3 && c3 == c1); //輸出true //通過類型別建立該類的物件例項 newInstance() ((DemoA) c1.newInstance()).print(); //輸出print } } class DemoA { void print() { System.out.println("print"); } }
二、JAVA獲取方法、成員變數、建構函式資訊
class DemoA { public void print() { System.out.println("print"); } public static void main(String[] args) throws NoSuchMethodException { DemoB.printMethodInfo("hello"); DemoB.printMethodInfo(1); } } class DemoB { public static void printMethodInfo(Object obj) throws NoSuchMethodException { Class objClass = obj.getClass(); //java.lang.String System.out.println("類名稱為:" + objClass.getName()); //String System.out.println(objClass.getSimpleName()); //getMethod獲取所有public的函式,包括父類繼承而來的 System.out.println(objClass.getMethod("toString").getName()); //getDeclaredMethod獲取的是所有該類自己宣告的方法,無視訪問許可權 System.out.println(objClass.getDeclaredMethod("toString").getName()); //方法也是物件 //遍歷方法列表 Method[] methods = objClass.getMethods(); for (Method method : methods) { System.out.print(method.getName() + "("); //遍歷引數名,並列印 Class[] parameterTypes = method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { System.out.print(parameterTypes[i].getSimpleName()); if (i < parameterTypes.length - 1) { System.out.print(","); } } System.out.println(")"); } //成員變數也是物件 //遍歷成員變數列表 Field[] fields = objClass.getFields(); for (Field field : fields) { //遍歷成員遍歷並列印 System.out.println(field.getType() + " " + field.getName()); } //建構函式也是物件 //建構函式列表 Constructor[] constructors = objClass.getConstructors(); for (Constructor constructor : constructors) { //建構函式方法名 System.out.print(constructor.getName()); //遍歷建構函式引數列表 Class[] typeParameters = constructor.getParameterTypes(); System.out.print("("); for (int i = 0; i < typeParameters.length; i++) { //列印引數名 System.out.print(typeParameters[i].getSimpleName()); if (i < typeParameters.length - 1) { System.out.print(","); } } System.out.println(")"); } } }
三、方法反射的基本操作
class DemoC { public void test(int a, int b) { System.out.println(a + b); } } class DemoA { /** * 反射就是將類別的各個組成部分進行剖析,可以得到每個組成部分,就可以對每一部分進行操作 * 在比較複雜的程式或框架中來使用反射技術,可以簡化程式碼提高程式的複用性。 * 我對invoke理解:運用反射,可以避過編譯時檢查, * 像方法test可以通過入參的形式呼叫,如果沒有test這個方法,使用傳統的呼叫方式,編譯都無法通過 * 可以編寫統一的反射方法,當增加或刪除某個方法時,這個反射方法就不用做一些變動了,可以簡化程式碼提高複用。 * 類 方法 欄位等都是在執行時才會執行,通過invoke方法,可以繞過編譯。 * 例如 ArrayList<String> arr = new ArrayList<>(); 可以通過反射繞過編譯,從而新增進其他型別的值 * Method method = arr.getClass().getMethod("add", Object.class); * method.invoke(arr, 20); * System.out.println(arr); 輸出20,已經新增進去了 */ public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, IllegalAccessException { DemoC democ = new DemoC(); Method test = democ.getClass().getMethod("test", new Class[]{int.class, int.class}); Object object = test.invoke(democ, new Object[]{10, 20}); } }