跳至主要內容

BeanUtils

chanchaw大约 2 分钟javaspring

概述

2026年4月25日 16:23:10 使用千问重写了本类

package com.cc.alltype;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author chanchaw
 * @create 2024-11-29 13:38
 */
public class BeanUtils {
    /**
     * 选择性拷贝:将 source 的非 null 属性拷贝给 target
     * 如果 source 中属性为 null,则保留 target 原有的值
     */
    public static <T> T copyPropertiesSelective(T source, T target) {
        if (source == null || target == null) {
            return target;
        }

        Class<?> clazz = source.getClass();
        // 获取所有声明的字段(包括私有)
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            // 跳过 static 和 final 字段
            if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) ||
                    java.lang.reflect.Modifier.isFinal(field.getModifiers())) {
                continue;
            }

            String fieldName = field.getName();

            // 构造 getter 和 setter 方法名
            String getterName = "get" + capitalize(fieldName);
            String setterName = "set" + capitalize(fieldName);

            try {
                // 获取 getter 方法
                Method getter = clazz.getMethod(getterName);
                // 获取字段值
                Object value = getter.invoke(source);

                // 核心逻辑:只有当值不为 null 时才进行拷贝
                if (value != null) {
                    // 获取 setter 方法
                    Method setter = clazz.getMethod(setterName, field.getType());
                    // 设置值
                    setter.invoke(target, value);
                }
            } catch (Exception e) {
                // 如果字段没有 getter/setter,或者访问失败,可以选择忽略或打印日志
                // e.printStackTrace();
            }
        }
        return target;
    }

    /**
     * 全量拷贝:无论 source 属性是否为 null,都强制拷贝给 target
     */
    public static <T> T copyPropertiesFull(T source, T target) {
        if (source == null || target == null) {
            return target;
        }

        // 这里直接使用 Spring 或 手动反射实现均可
        // 为了保持不依赖外部库,这里使用手动反射实现,逻辑与上面类似,但不判断 null
        Class<?> clazz = source.getClass();
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) ||
                    java.lang.reflect.Modifier.isFinal(field.getModifiers())) {
                continue;
            }

            String fieldName = field.getName();
            String getterName = "get" + capitalize(fieldName);
            String setterName = "set" + capitalize(fieldName);

            try {
                Method getter = clazz.getMethod(getterName);
                Object value = getter.invoke(source); // 获取值(可能是 null)

                Method setter = clazz.getMethod(setterName, field.getType());
                setter.invoke(target, value); // 直接设置(覆盖旧值)
            } catch (Exception e) {
                // 忽略异常
            }
        }
        return target;
    }

    // 辅助方法:首字母大写
    private static String capitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        return name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    /**
     * 对象转Map
     * @param object
     * @return
     */
    public static Map beanToMap(Object object) throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter!=null ? getter.invoke(object) : null;
            map.put(key, value);
        }
        return map;
    }

    /**
     * map转对象
     * @param map
     * @param beanClass
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T mapToBean(Map map, Class<T> beanClass) throws Exception {
        T object = beanClass.newInstance();
        BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            Method setter = property.getWriteMethod();
            if (setter != null) {
                setter.invoke(object, map.get(property.getName()));
            }
        }
        return object;
    }
}