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);
}
}
PropertyDescriptor 數組,包含讀/寫方法、屬性類型、屬性編輯器等元數據。Method,參數類型即屬性類型(基本類型返回 TYPE)。Object[],基本類型值會自動裝箱傳入。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);
Introspector.getBeanInfo() 緩存機制依賴類加載器,建議應用層再封裝一層 ConcurrentHashMap, BeanInfo> 。method.setAccessible(true) 並緩存,避免重複安全檢查。反射配合內省機制,能優雅實現「請求參數 → JavaBean」的自動映射。關鍵在於正確識別基本類型(TYPE 常量)並統一轉換邏輯。此模式廣泛應用於 MVC 框架(Struts、Spring MVC)的數據綁定模塊,理解其原理有助於排查綁定異常與性能優化。