java.lang.reflect 讓程式在運行時動態:
廣泛應用於:IDE、除錯器、ORM、DI 容器、序列化、測試框架、插件系統。
public class Employee {
public String empNum;
public String empName;
public Employee() { this("1", "King"); }
public Employee(String num, String name) { empNum = num; empName = name; }
public String toString() { return "Emp: " + empNum + ", " + empName; }
}
import java.lang.reflect.*;
public class AnalyzeClass {
public static void main(String[] args) {
Employee e = new Employee();
Class<?> clazz = e.getClass();
System.out.println("類別名稱: " + clazz.getName());
System.out.println("父類別: " + clazz.getSuperclass().getName());
int mods = clazz.getModifiers();
System.out.println("public: " + Modifier.isPublic(mods));
System.out.println("final: " + Modifier.isFinal(mods));
System.out.println("abstract: " + Modifier.isAbstract(mods));
}
}
public class DumpMethods {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName(args[0]); // 傳入 java.util.Stack
for (Method m : c.getDeclaredMethods()) {
System.out.println(m);
}
}
}
// 輸出範例:
// public synchronized java.lang.Object java.util.Stack.pop()
// public java.lang.Object java.util.Stack.push(java.lang.Object)
// public boolean java.util.Stack.empty()
// ...
public class DumpFields {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName(args[0]); // 傳入 Employee
for (Field f : c.getDeclaredFields()) {
System.out.println(f);
}
}
}
// 輸出:
// public java.lang.String Employee.empNum
// public java.lang.String Employee.empName
public class DumpConstructors {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName(args[0]);
for (Constructor<?> cons : c.getDeclaredConstructors()) {
System.out.println(cons);
for (Class<?> pt : cons.getParameterTypes()) {
System.out.println(" 參數: " + pt.getName());
}
}
}
}
// 輸出:
// public Employee(java.lang.String,java.lang.String)
// 參數: java.lang.String
// 參數: java.lang.String
// public Employee()
public class DynamicInvoke {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.example.MyService");
Object instance = clazz.getDeclaredConstructor().newInstance();
Method m = clazz.getMethod("setProperties", Properties.class);
Properties props = new Properties();
props.setProperty("key", "value");
m.invoke(instance, props);
}
}
| 面向 | 影響 | 建議 |
|---|---|---|
| 效能 | 反射比直接呼叫慢 10-100 倍 | 熱點路徑快取 Method/Field/Constructor 物件;JDK 7+ MethodHandle 更快 |
| 安全性 | 可破壞封裝、繞過泛型檢查 | SecurityManager 限制 suppressAccessChecks;模組化 (JPMS) 封裝內部 API |
| 維護性 | 編譯期無法檢查字串名稱 | 善用常數、註解驅動、框架封裝 |
java.lang.invoke.MethodHandles.lookup() 取代部分反射module-info.java 宣告 opens 才能深度反射