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

Java 反射實戰:動態獲取類別欄位名稱與值

     編輯:Java 相關知識

問題背景

在類別中定義屬性 abc,如何動態獲取這個變數的名稱字串「abc」?這是一個有趣且實用的問題,解決方案核心在於 Java 反射機制。

解決方案:使用反射遍歷欄位

Java 提供強大的反射機制,比動態語言更動態。以下提供一個通用工具方法,動態獲取物件中所有宣告欄位的名稱與值:

public class MyTools {
    public static void setAllComponentsName(Object obj) {
        // 獲取物件對應類別中所有宣告欄位
        Field[] fields = obj.getClass().getDeclaredFields();
        for (int i = 0, len = fields.length; i < len; i++) {
            // 獲取欄位名稱
            String varName = fields[i].getName();
            try {
                // 保存原訪問控制權限
                boolean accessFlag = fields[i].isAccessible();
                // 修改訪問控制權限,允許存取 private 欄位
                fields[i].setAccessible(true);
                // 獲取物件中該欄位對應的實際值
                Object value = fields[i].get(obj);
                System.out.println("物件包含欄位: " + varName + " = " + value);
                // 恢復原訪問控制權限
                fields[i].setAccessible(accessFlag);
            } catch (IllegalArgumentException | IllegalAccessException ex) {
                ex.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        // 測試:獲取 JLabel 所有宣告欄位名稱與值
        setAllComponentsName(new JLabel("測試"));
    }
}

關鍵技術點解析

1. 突破封裝性:setAccessible(true)

fields[i].setAccessible(true) 是核心關鍵。私有欄位在類別外無法直接存取,透過此設定可改變私有欄位存取權限。這雖然強大,但也引發安全性擔憂——私有成員竟可被外部存取。不過在需要解決問題的情境下(如序列化、除錯工具、測試框架),此特權被廣泛採納。

2. 獲取實際欄位值:fields[i].get(obj)

此行取得傳入物件 obj 中類別欄位 fields[i] 對應的實際值。例如類別 A 有 int abc 欄位,擁有兩個實例 a1、a2。呼叫 fields[i].get(a1) 獲取 a1 的具體 abc 值;呼叫 fields[i].get(a2) 獲取 a2 的 abc 值。

實際運行結果

以 JLabel("測試") 為例,輸出所有宣告欄位名稱與值:

物件包含欄位: uiClassID = LabelUI
物件包含欄位: mnemonic = 0
物件包含欄位: mnemonicIndex = -1
物件包含欄位: text = 測試
物件包含欄位: defaultIcon = null
物件包含欄位: disabledIcon = null
物件包含欄位: disabledIconSet = false
物件包含欄位: verticalAlignment = 0
物件包含欄位: horizontalAlignment = 10
物件包含欄位: verticalTextPosition = 0
物件包含欄位: horizontalTextPosition = 11
物件包含欄位: iconTextGap = 4
物件包含欄位: labelFor = null
物件包含欄位: LABELED_BY_PROPERTY = labeledBy

應用場景

  • 通用物件檢查/除錯工具
  • 序列化/反序列化框架
  • 測試框架自動驗證物件狀態
  • ORM 框架映射欄位與資料庫欄位
  • 動態表單生成與資料綁定

注意事項

  • getDeclaredFields() 僅返回當前類別宣告欄位,不含繼承欄位。需遞迴遍歷父類別獲取完整欄位。
  • 頻繁使用反射有效能開銷,效能敏感場合建議快取 Field 物件。
  • 修改 setAccessible 可能受 SecurityManager 限制。
  • 僅能獲取宣告欄位名稱,無法獲取區域變數名稱(編譯時已擦除)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved