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

Java 反射機制實戰:獲取類屬性值的通用工具類實現

     編輯:Java 相關知識

反射獲取屬性值的核心思路

Java 反射機制允許運行時動態獲取類的結構信息。獲取屬性值的標準模式是:通過反射獲取字段名 → 按 JavaBean 規範拼接 getter 方法名(如 userName → getUserName()) → 通過反射調用 getter 方法獲取值。這種方式比直接訪問字段更安全,尊重了封裝性。

通用基類實現

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 參數基類:提供通過反射獲取所有屬性名與值的功能
 * 子類繼承此類即可獲得 getClassInfo() 能力
 */
public class ParameterBase {

    /**
     * 獲取當前對象所有屬性及其值的 Map
     * @return 屬性名-值映射
     */
    public Map<String, String> getClassInfo() {
        Map<String, String> fieldsAndValues = new HashMap<>();
        
        // 獲取聲明的所有字段(包含 private)
        Field[] fields = this.getClass().getDeclaredFields();
        
        for (Field field : fields) {
            String fieldName = field.getName();
            // 通過反射調用 getter 獲取值
            String value = getFieldValue(this, fieldName);
            fieldsAndValues.put(fieldName, value);
        }
        
        return fieldsAndValues;
    }

    /**
     * 獲取指定屬性的值
     */
    private String getFieldValue(Object owner, String fieldName) {
        return invokeMethod(owner, fieldName, null).toString();
    }

    /**
     * 反射調用 getter 方法
     * @param owner 目標對象
     * @param fieldName 屬性名
     * @param args 方法參數(getter 無參)
     * @return 方法返回值
     */
    private Object invokeMethod(Object owner, String fieldName, Object[] args) {
        Class<? extends Object> ownerClass = owner.getClass();
        
        // 拼接 getter 方法名:首字母大寫 + "get" 前綴
        String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        
        Method method = null;
        try {
            method = ownerClass.getMethod(methodName);
        } catch (NoSuchMethodException e) {
            // 沒有對應的 getter,返回空字符串
            return "";
        } catch (SecurityException e) {
            // 安全限制,返回空字符串
            return "";
        }
        
        try {
            return method.invoke(owner);
        } catch (Exception e) {
            // 調用異常,返回空字符串
            return "";
        }
    }
}

實體類與測試代碼

public class User extends ParameterBase {
    private String userName;
    private String passWorld;

    // 標準 getter/setter
    public String getUserName() { return userName; }
    public void setUserName(String userName) { this.userName = userName; }
    
    public String getPassWorld() { return passWorld; }
    public void setPassWorld(String passWorld) { this.passWorld = passWorld; }

    public static void main(String[] args) {
        User u = new User();
        u.setUserName("aaaaa");
        u.setPassWorld("123");
        
        // 獲取所有屬性值
        System.out.println(u.getClassInfo());
        // 輸出:{passWorld=123, userName=aaaaa}
    }
}

關鍵技術點解析

1. getDeclaredFields() vs getFields()

  • getDeclaredFields():獲取類聲明的所有字段,包含 private、protected、default、public,**不包含繼承的字段**
  • getFields():只獲取 public 字段,**包含繼承的字段**

2. 方法名拼接規範

遵循 JavaBean 規範:

  • boolean 類型可用 isXxx() 或 getXxx()
  • 其他類型統一用 getXxx()
  • 首字母大寫:userName → getUserName()

3. 異常處理策略

代碼捕獲了三類異常並統一返回空字符串:

  • NoSuchMethodException:沒有對應的 getter 方法
  • SecurityException:安全管理器禁止訪問
  • Exception:調用過程中的其他異常(如 IllegalAccessException、InvocationTargetException)

進階改進方向

支持 boolean 類型的 isXxx() 獲取器

private String getGetterName(String fieldName, Class<?> fieldType) {
    if (fieldType == boolean.class || fieldType == Boolean.class) {
        return "is" + capitalize(fieldName);
    }
    return "get" + capitalize(fieldName);
}

private String capitalize(String str) {
    return str.substring(0, 1).toUpperCase() + str.substring(1);
}

處理繼承鏈上的字段

public Map<String, String> getClassInfoIncludingInherited() {
    Map<String, String> result = new HashMap<>();
    Class<?> clazz = this.getClass();
    
    while (clazz != null && clazz != Object.class) {
        for (Field field : clazz.getDeclaredFields()) {
            if (!result.containsKey(field.getName())) {
                result.put(field.getName(), getFieldValue(this, field.getName()));
            }
        }
        clazz = clazz.getSuperclass();
    }
    return result;
}

返回原始類型而非字符串

public Map<String, Object> getClassInfoAsObject() {
    Map<String, Object> result = new HashMap<>();
    for (Field field : this.getClass().getDeclaredFields()) {
        result.put(field.getName(), invokeMethod(this, field.getName(), null));
    }
    return result;
}

應用場景

  • 通用的對象轉 Map 工具
  • 日誌記錄:自動序列化對象所有屬性
  • 表單數據綁定與驗證
  • 通用的數據導出(Excel、CSV)
  • 調試工具:快速打印對象狀態

性能提示

反射調用比直接調用慢,若在高頻熱點路徑使用,建議:

  1. 緩存 Method 對象(使用 ConcurrentHashMap)
  2. 考慮使用 MethodHandle(Java 7+)
  3. 或使用成熟庫如 Apache Commons BeanUtils、FastJSON、Jackson
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved