首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 反射機制完整入門範例

     編輯:Java 相關知識

Java 反射核心 API 實戰示範

反射允許程式在執行期檢查類別結構、動態建立實例、呼叫方法、存取欄位,是框架(Spring、Hibernate、MyBatis)實現解耦與自動裝配的基石。本文透過完整範例展示反射常用操作。

目標類別

package reflection;

public class User {
    private String name;
    private int age;

    public User() {}
    public User(String name, int age) {
        this.name = name; this.age = age;
    }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public void sayHello() { System.out.println("Hi, " + name); }
}

反射操作大全

package reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionGuide {
    public static void main(String[] args) throws Exception {
        Class<User> clazz = User.class; // 方式一:類字面常數
        // Class clazz = Class.forName("reflection.User"); // 方式二:字串載入

        // 1. 列出所有宣告的欄位(含 private)
        System.out.println("=== Fields ===");
        for (Field f : clazz.getDeclaredFields()) {
            System.out.println(f.getName() + " : " + f.getType().getSimpleName());
        }

        // 2. 列出所有宣告的方法
        System.out.println("\n=== Methods ===");
        for (Method m : clazz.getDeclaredMethods()) {
            System.out.println(m.getName() + " : " + m.getReturnType().getSimpleName());
        }

        // 3. 取得建構子並實例化
        Constructor<User> ctor = clazz.getDeclaredConstructor(String.class, int.class);
        User user = ctor.newInstance("Alice", 25);

        // 4. 存取 private 欄位(需 setAccessible)
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);
        System.out.println("\n原始 name: " + nameField.get(user));
        nameField.set(user, "Bob");
        System.out.println("修改後 name: " + nameField.get(user));

        // 5. 呼叫方法
        Method sayHello = clazz.getDeclaredMethod("sayHello");
        sayHello.invoke(user); // 輸出: Hi, Bob

        // 6. 呼叫 setter/getter
        Method setAge = clazz.getMethod("setAge", int.class);
        setAge.invoke(user, 30);
        Method getAge = clazz.getMethod("getAge");
        System.out.println("年齡: " + getAge.invoke(user));
    }
}

核心 API 對照表

需求API備註
載入類別Class.forName("全限定名")會觸發靜態初始化
取得 public 建構子clazz.getConstructor(參數型別...)拋 NoSuchMethodException
取得任意建構子clazz.getDeclaredConstructor(參數型別...)需 setAccessible(true)
建立實例constructor.newInstance(引數...)自動處理拋出的異常
取得 public 方法clazz.getMethod(名稱, 參數型別...)搜尋父類別
取得任意方法clazz.getDeclaredMethod(名稱, 參數型別...)僅本類別,需 setAccessible
呼叫方法method.invoke(實例, 引數...)static 方法實例傳 null
存取 public 欄位clazz.getField(名稱)搜尋父類別
存取任意欄位clazz.getDeclaredField(名稱)需 setAccessible(true)

效能與安全提醒

  • 效能:反射比直接呼叫慢 10~100 倍(JIT 難優化),熱點路徑請快取 `Method`/`Field`/`Constructor` 物件。
  • 安全:`setAccessible(true)` 可能被 `SecurityManager` 禁止;模組化系統(Java 9+)需 `opens` 套件。
  • 替代方案:Kryo、Jackson、AutoValue 等庫透過字節碼生成避免反射開銷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved