首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 反射實現物件轉 Map:非空屬性過濾的完整工具類代碼

     編輯:程式設計綜合問答

需求分析

將任意 Java 物件的非空屬性轉為 Map<String, Object>,鍵為屬性名,值為屬性值。支援兩種介面:

Map<String, Object> objToMap(Object obj, Class<?> clazz);
Map<String, Object> objToMap(Object obj);  // 自動獲取 obj.getClass()

完整工具類實現

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

public class BeanMapUtils {

    /** 物件轉 Map,僅包含非 null 屬性 */
    public static Map<String, Object> objToMap(Object obj) {
        if (obj == null) return new HashMap<>();
        return objToMap(obj, obj.getClass());
    }

    /** 指定類別轉 Map(可處理父類屬性) */
    public static Map<String, Object> objToMap(Object obj, Class<?> clazz) {
        Map<String, Object> map = new HashMap<>();
        if (obj == null || clazz == null) return map;

        // 遞迴處理父類鏈
        Class<?> current = clazz;
        while (current != null && current != Object.class) {
            Field[] fields = current.getDeclaredFields();
            for (Field field : fields) {
                // 跳過 static、final、transient、synthetic 欄位
                int mod = field.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod) 
                    || Modifier.isTransient(mod) || Modifier.isVolatile(mod)) {
                    continue;
                }

                field.setAccessible(true);  // 破壞封裝存取 private
                try {
                    Object value = field.get(obj);
                    if (value != null) {  // 核心:非空才放入
                        map.put(field.getName(), value);
                    }
                } catch (IllegalAccessException e) {
                    // 忽略不可存取欄位
                }
            }
            current = current.getSuperclass();  // 向上處理父類
        }
        return map;
    }
}

使用範例

public class User {
    private String name = "Alice";
    private Integer age = 25;
    private String email = null;  // 空值
    private static String CONST = "IGNORED";
    private transient String temp = "IGNORED";
}

// 測試
User u = new User();
Map<String, Object> map = BeanMapUtils.objToMap(u);
// 結果:{name=Alice, age=25}  ← email、CONST、temp 皆被過濾

進階擴展建議

需求實現方式
支援 Getter 方法(isXxx/getXxx)掃描 getMethods(),配合 Introspector
自訂命名策略(駝峰/下劃線)引入 PropertyNamingStrategy (Jackson)
日期/集合/巢狀物件序列化遞迴呼叫或註冊 TypeAdapter
效能優化(頻繁呼叫)快取 Field[] 陣列,使用 ConcurrentHashMap<Class, Field[]>
Spring 環境直接用 BeanUtils.describe(obj) 或 MapStruct

現成庫推薦

  • Apache Commons BeanUtils:PropertyUtils.describe(obj),成熟穩定
  • Spring BeanUtils:BeanUtils.describe(obj),Spring 專案零依賴
  • Jackson:objectMapper.convertValue(obj, Map.class),支援註解控制
  • MapStruct:編譯期生成映射代碼,效能最佳

總結

Java 反射實現物件轉 Map 完全可行。核心邏輯:getDeclaredFields() → setAccessible(true) → field.get(obj) → 非空判斷 → 放入 Map。生產環境建議優先使用成熟庫(Commons BeanUtils/Jackson/MapStruct),自寫工具類需注意效能快取、父類遞迴、特殊修飾符過濾等細節。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved