反射讓程式在執行期檢視、操作類別結構:欄位、方法、建構子、註解等。適用於框架開發、序列化、依賴注入、動態代理等場景。
package reflection;
public class User {
public String name;
protected int age;
String address; // package-private
private String sex;
public User() {}
public User(String name, int age, String sex) {
this.name = name; this.age = age; this.sex = sex;
}
// getter/setter 略...
}
package reflection;
import java.lang.reflect.*;
public class Demo01 {
public static void main(String[] args) {
try {
// 1. 獲取 Class 物件
Class<?> clazz = Class.forName("reflection.User");
// 2. 類別基本資訊
System.out.println("=== 類別名稱 ===");
System.out.println("getName(): " + clazz.getName()); // 完整限定名
System.out.println("getSimpleName(): " + clazz.getSimpleName()); // 簡單名
System.out.println("getCanonicalName(): " + clazz.getCanonicalName());
// 3. 獲取所有宣告欄位(含 private)
System.out.println("\n=== 欄位資訊 ===");
Field[] fields = clazz.getDeclaredFields(); // getFields() 僅 public
for (Field f : fields) {
System.out.println(clazz.getDeclaredField(f.getName()));
}
// 4. 獲取所有宣告方法
System.out.println("\n=== 方法資訊 ===");
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
System.out.println(m.getName() + " --> " + m);
}
// 依名稱精確獲取(含參數型別區分多載)
System.out.println("getName: " + clazz.getDeclaredMethod("getName"));
System.out.println("setSex: " + clazz.getDeclaredMethod("setSex", String.class));
// 5. 獲取建構子
System.out.println("\n=== 建構子資訊 ===");
Constructor<?>[] constructors = clazz.getConstructors(); // 僅 public
for (Constructor<?> c : constructors) {
System.out.println(c);
}
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
=== 類別名稱 ===
getName(): reflection.User
getSimpleName(): User
getCanonicalName(): reflection.User
=== 欄位資訊 ===
public java.lang.String reflection.User.name
protected int reflection.User.age
java.lang.String reflection.User.address
private java.lang.String reflection.User.sex
=== 方法資訊 ===
getName --> public java.lang.String reflection.User.getName()
setName --> public void reflection.User.setName()
setSex --> public void reflection.User.setSex(java.lang.String)
getSex --> public java.lang.String reflection.User.getSex()
getAge --> public int reflection.User.getAge()
getName: public java.lang.String reflection.User.getName()
setSex: public void reflection.User.setSex(java.lang.String)
=== 建構子資訊 ===
public reflection.User()
public reflection.User(java.lang.String,int,java.lang.String)
| 需求 | 方法 | 範圍 |
|---|---|---|
| 所有 public 欄位 | getFields() | 含繼承 |
| 本類宣告所有欄位 | getDeclaredFields() | 含 private,不含繼承 |
| 所有 public 方法 | getMethods() | 含繼承 |
| 本類宣告所有方法 | getDeclaredMethods() | 含 private,不含繼承 |
| public 建構子 | getConstructors() | |
| 所有宣告建構子 | getDeclaredConstructors() | 含 private |
// 破壞封裝存取 private 欄位
Field sexField = clazz.getDeclaredField("sex");
sexField.setAccessible(true); // 關鍵:取消存取檢查
User user = new User();
sexField.set(user, "Male");
System.out.println(sexField.get(user)); // 輸出:Male
// 呼叫 private 方法
Method secret = clazz.getDeclaredMethod("internalCheck");
secret.setAccessible(true);
secret.invoke(user);
setAccessible(true) 可能被 SecurityManager 禁止module-info.java 開放 opens 才能深度反射