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

Java 反射實戰:動態識別並處理 JavaBean 基本類型屬性

     編輯:Java 程式設計入門

反射機制核心價值:運行時類型發現與操作

Java 反射 API(java.lang.reflect)允許程序在運行時檢查類結構、創建實例、調用方法、訪問字段,是框架開發(Spring、Hibernate、Jackson 等)的基石。本文聚焦一個實際場景:根據 HTTP 請求參數自動填充 JavaBean,正確處理基本類型與包裝類轉換。

基本類型在反射中的特殊表現

Java 八大基本類型(boolean、byte、short、int、long、float、double、char)不是類,但每個都有對應的包裝類(Boolean、Byte...)在 java.lang 中。反射中通過 Class 對象表示類型:

  • int.class == Integer.TYPE(非 Integer.class)
  • boolean.class == Boolean.TYPE
  • ... 以此類推

這區別至關重要:Method.getParameterTypes() 返回基本類型時為 Integer.TYPE,而非 Integer.class。

通用屬性填充實現

public class BeanPopulator {

    public static void populate(HttpServletRequest request, Object bean) throws Exception {
        BeanInfo info = Introspector.getBeanInfo(bean.getClass());
        PropertyDescriptor[] pds = info.getPropertyDescriptors();

        for (PropertyDescriptor pd : pds) {
            String name = pd.getName();
            String value = request.getParameter(name);
            if (value == null) continue; // 參數缺失跳過

            Method setter = pd.getWriteMethod();
            if (setter == null) continue; // 唯讀屬性跳過

            Class paramType = setter.getParameterTypes()[0];
            Object converted = convert(value, paramType);
            setter.invoke(bean, converted);
        }
    }

    private static Object convert(String value, Class targetType) {
        // 基本類型與包裝類統一處理
        if (targetType == String.class) return value;
        if (targetType == int.class || targetType == Integer.class) return Integer.valueOf(value);
        if (targetType == long.class || targetType == Long.class) return Long.valueOf(value);
        if (targetType == double.class || targetType == Double.class) return Double.valueOf(value);
        if (targetType == float.class || targetType == Float.class) return Float.valueOf(value);
        if (targetType == boolean.class || targetType == Boolean.class) return Boolean.valueOf(value);
        if (targetType == byte.class || targetType == Byte.class) return Byte.valueOf(value);
        if (targetType == short.class || targetType == Short.class) return Short.valueOf(value);
        if (targetType == char.class || targetType == Character.class) {
            if (value.length() != 1) throw new IllegalArgumentException("Char needs single char");
            return value.charAt(0);
        }
        // 可擴展:Date、Enum、BigDecimal 等
        throw new UnsupportedOperationException("Unsupported type: " + targetType);
    }
}

關鍵技術點解析

  1. Introspector:JavaBean 內省標準 API,獲取 PropertyDescriptor 數組,包含讀/寫方法、屬性類型、屬性編輯器等元數據。
  2. PropertyDescriptor.getWriteMethod():返回 setter Method,參數類型即屬性類型(基本類型返回 TYPE)。
  3. Method.invoke():參數需為 Object[],基本類型值會自動裝箱傳入。
  4. 類型轉換策略:統一處理基本類型與包裝類,避免 if (type == Integer.class || type == int.class) 冗余判斷。

進階擴展:類型轉換器註冊表

為支持自定義類型(LocalDate、BigDecimal、Enum 等),可引入 Converter 接口與註冊中心:

public interface Converter {
    T convert(String value);
}

public class ConverterRegistry {
    private static final Map, Converter> REGISTRY = new HashMap<>();

    static {
        register(Integer.class, Integer::valueOf);
        register(int.class, Integer::valueOf);
        register(LocalDate.class, LocalDate::parse);
        // ...
    }

    public static  void register(Class type, Converter converter) {
        REGISTRY.put(type, converter);
    }

    @SuppressWarnings("unchecked")
    public static  Converter get(Class type) {
        return (Converter) REGISTRY.get(type);
    }
}

// 使用
Converter converter = ConverterRegistry.get(paramType);
if (converter != null) return converter.convert(value);

性能優化建議

  • 緩存 BeanInfo:Introspector.getBeanInfo() 緩存機制依賴類加載器,建議應用層再封裝一層 ConcurrentHashMap, BeanInfo>。
  • 緩存 Method 對象:反射調用前 method.setAccessible(true) 並緩存,避免重複安全檢查。
  • 考慮字節碼生成:極高性能場景可用 ASM/ByteBuddy 生成專用填充類,消除反射開銷。

總結

反射配合內省機制,能優雅實現「請求參數 → JavaBean」的自動映射。關鍵在於正確識別基本類型(TYPE 常量)並統一轉換邏輯。此模式廣泛應用於 MVC 框架(Struts、Spring MVC)的數據綁定模塊,理解其原理有助於排查綁定異常與性能優化。

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