反射是 Java 語言的核心特性之一,允許程式在執行期動態獲取類別資訊並操作其成員。本文聚焦於方法反射,說明如何透過方法名稱與參數列表精準定位方法、呼叫方法,以及處理私有方法的存取權限問題。
在 Java 中,單靠方法名稱不足以唯一識別一個方法,必須結合參數列表(參數型別、數量、順序)才能精確定位。這也是為什麼 Class.getDeclaredMethod(String name, Class>... parameterTypes) 需要傳入參數型別陣列的原因。
method.invoke()取得 Method 物件後,透過 invoke(Object obj, Object... args) 即可在指定物件上執行該方法。第一個參數是目標物件實例(靜態方法可傳 null),後續參數對應方法簽名的引數。
package com.tsh.reflect;
import java.lang.reflect.Method;
public class ReflectDemo {
public static void main(String[] args) {
P p = new P();
Class<?> c = P.class;
try {
// 獲取參數為 String 的 print 方法
Method method = c.getDeclaredMethod("print", String.class);
// 呼叫方法,傳入實例 p 與引數 "ssss"
method.invoke(p, "ssss");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class P {
public void print(int a, int b) {
System.out.println(a + b);
}
public void print(String a) {
System.out.println(a);
}
}
IllegalAccessException若目標方法是 private,直接呼叫 invoke() 會拋出 java.lang.IllegalAccessException。解決方式是在呼叫前設定 method.setAccessible(true),暴力破解存取檢查(需安全管理員允許)。
Method privateMethod = c.getDeclaredMethod("secret", String.class);
privateMethod.setAccessible(true); // 關鍵步驟
privateMethod.invoke(p, "hidden");
getMethod() 僅能獲取 public 方法(含繼承);getDeclaredMethod() 可獲取該類別自行宣告的所有方法(不含繼承),不受修飾詞限制。Method 物件或使用 MethodHandle。module-info.java 中 opens 相關套件。掌握方法反射,能讓你編寫更靈活的框架、測試工具或動態代理邏輯,是進階 Java 開發者的必備技能。