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

Java 反射機制實戰:獲取類別結構資訊完整指南

     編輯:Java 相關知識

反射核心價值

反射讓程式在執行期檢視、操作類別結構:欄位、方法、建構子、註解等。適用於框架開發、序列化、依賴注入、動態代理等場景。

目標類別定義

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)

關鍵 API 對照表

需求方法範圍
所有 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);

效能與安全提醒

  • 反射比直接呼叫慢 10-100 倍,熱點路徑避免頻繁使用
  • setAccessible(true) 可能被 SecurityManager 禁止
  • 模組化系統(Java 9+)需在 module-info.java 開放 opens 才能深度反射
  • 優先考慮介面程式設計、註解處理器、方法柄 等替代方案
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved