java反射——實現程式的動態性
轉自http://uuhorse.iteye.com/blog/1706466
① 建立物件
如果知道一個型別,很容易使用new操作符建立一個類的例項。但是如果在編譯時並不知道具體要例項化的是哪個類的物件,如何建立該例項呢?
Java中提供Class.forName(String className)從一個字串(含包的類全名稱)載入一個類,再利用newInstance方法建立該類的例項。
//動態建立類物件
public static Object createObject(String className) {
Object object = null;
try {
Class classDefinition = Class.forName(className);
object = classDefinition.newInstance();
} catch (InstantiationException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (ClassNotFoundException e) {
System.out.println(e);
}
return object;
}
當然,也可以先獲取一個類的Constructor,再呼叫其newInstance方法建立物件。不同的是,constructor物件的newInstance方法需要傳遞一個物件陣列作為構造方法的引數列表。
//使用Constructor動態建立物件
public static Object createObject(Constructor constructor, Object[] arguments) {
System.out.println("Constructor: " + constructor.toString());
Object object = null;
try {
object = constructor.newInstance(arguments);
System.out.println("Object: " + object.toString());
return object;
} catch (InstantiationException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (IllegalArgumentException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
return object;
}
② 獲取/設定欄位值利用Reflection API獲取或者設定欄位的值,首先要得到Class物件,然後利用Class物件的getField方法取得相應的欄位Field物件,然後呼叫Field物件對應的getXXX/setXXX方法獲取或者設定屬性的值。Filed物件提供getInt/setInt、getLong/setLong等方法對基本型別的屬性進行值的獲取和設定,可以直接使用get/set方法獲取複雜型別屬性的值(返回一個物件值/傳遞一個物件值作為引數)。
具體操作方法見如下程式碼片段。當然,若試圖獲取/設定一個非public的欄位值(getField方法也不能獲取非pubic的屬性物件,可以嘗試使用getDeclaredField方法),將產生IllegalAccessException,可以通過setAccessible(true)使非public的欄位可見,然後對欄位值進行訪問。
// 獲取欄位值
static void getFiledValue(Object o, String filedName) {
Class c = o.getClass();
Field filed;
Object value;
try {
filed = c.getField(filedName);
// filed = c.getDeclaredField(filedName);
// filed.setAccessible(true); //修改欄位訪問許可權
value = filed.get(o); //可使用getInt、getLong等(若知曉欄位基本型別)
System.out.println(filedName + ": " + value.toString());
} catch (NoSuchFieldException e) {
System.out.println(e);
} catch (SecurityException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
}
}
// 修改欄位值
public static void setFieldValue(Object o, String filedName, Object value) {
Field filed;
Class c = o.getClass();
try {
filed = c.getField(filedName);
// filed = c.getDeclaredField(filedName);
// filed.setAccessible(true); //修改欄位訪問許可權
filed.set(o, value); //可使用setInt、setLong等(若知曉欄位基本型別)
} catch (NoSuchFieldException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
}
}
③ 呼叫方法
方法呼叫的過程類似於設定欄位值的過程,首先要得到Class物件,然後呼叫getMethod方法得到方法Method的物件,getMethod方法要求傳遞兩個引數,一個是方法名,第二個是Class[],即方法引數列表中各引數對應的型別的陣列。然後執行Method物件的invoke方法,進行方法的呼叫,invoke方法需要傳遞兩個引數,第一個是方法繫結的物件,第二個是方法的引數列表。如果是static的方法,則第一個引數將自動被忽略(可為null)。
同理,對於非public的方法,可以使用getDeclaredMethod方法獲取Method物件,並使用setAccessible設定其可見性。
//動態呼叫方法
public static Object callMethod(Object o, String methodName,
Class paramsType[], Object paramsValue[]) {
Object result = null;
Class c;
Method method;
try {
c = o.getClass();
method = c.getMethod(methodName, paramsType);
// method = c.getDeclaredMethod(methodName, paramsType);
// method.setAccessible(true);
result = method.invoke(o, paramsValue);
} catch (NoSuchMethodException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
return result;
}
相關文章
- java 反射和動態代理Java反射
- Laravel 動態屬性的實現Laravel
- Java反射動態修改註解的值Java反射
- Java動態代理和反射機制Java反射
- 反射的妙用:C#通過反射動態生成型別繼承介面並實現反射C#型別繼承
- Java反射-屬性Java反射
- 深入理解 Java 反射和動態代理Java反射
- SAP ABAP和Java的動態代理實現Java
- Java中動態規則的實現方式Java
- c++ web框架實現之靜態反射實現C++Web框架反射
- java反射之動態代理學習筆記Java反射筆記
- Java 反射修改類的常量值、靜態變數值、屬性值Java反射變數
- 00024.06 反射:反射的應用2:動態建立物件反射物件
- 動手編寫—動態陣列(Java實現)陣列Java
- Java動態代理 jdk和cglib的實現比較JavaJDKCGLib
- 小程式頁面動態配置實現
- 動態棧的實現
- PHP 反射之動態代理PHP反射
- java 反射之操作靜態MethodJava反射
- 基於NACOS和JAVA反射機制動態更新JAVA靜態常量非@Value註解Java反射
- 死磕java底層(三)—反射、動態代理和註解Java反射
- Mybatis之介面程式設計--JAVA動態代理的最佳展現MyBatis程式設計Java
- Java陣列如何實現動態初始化Java陣列
- java實現用一個變數表示多個屬性的狀態Java變數
- FSM狀態機及C#反射實現邏輯C#反射
- Protobuf_動態訊息-反射反射
- 使用PHP實現動態代理IP的示例程式碼PHP
- Java提高班(六)反射和動態代理(JDK Proxy和Cglib)Java反射JDKCGLib
- Java 動態性(4) – 位元組碼操作Java
- JVM是如何實現反射的JVM反射
- 你可以零侵入式實現小程式的全域性狀態管理嗎
- Java的反射Java反射
- 你必須瞭解的反射——反射來實現實體驗證反射
- 藉助 Webpack 靜態分析能力實現程式碼動態載入Web
- Java反射增強:程式碼模型Java反射模型
- Java 反射程式設計(下)Java反射程式設計
- spring+groovy實現動態程式碼注入執行Spring
- 微信小程式底部實現自定義動態Tabbar微信小程式tabBar
- Python 類的動態屬性、動態方法在 IDE 裡面自動補全;這個有辦法實現嗎?PythonIDE