Java反射赋值属性案例怎么写

wen java案例 19

本文目录导读:

Java反射赋值属性案例怎么写

  1. 基础反射赋值示例
  2. 高级应用:对象属性拷贝
  3. 性能优化:缓存反射元数据
  4. 运行结果
  5. 注意事项

我来为您提供一个Java反射赋值的完整案例。

基础反射赋值示例

实体类

public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    // 无参构造
    public User() {}
    // getter和setter方法
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    @Override
    public String toString() {
        return "User{id=" + id + ", name='" + name + "', age=" + age + ", email='" + email + "'}";
    }
}

反射赋值工具类

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class ReflectUtil {
    /**
     * 通过setter方法反射赋值
     */
    public static <T> T setFieldBySetter(T object, String fieldName, Object value) {
        try {
            // 获取对象的Class
            Class<?> clazz = object.getClass();
            // 构建setter方法名
            String setterName = "set" + fieldName.substring(0, 1).toUpperCase() 
                              + fieldName.substring(1);
            // 获取setter方法
            Method setter = clazz.getMethod(setterName, value.getClass());
            // 调用setter方法
            setter.invoke(object, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
    /**
     * 通过Field直接赋值(忽略访问修饰符)
     */
    public static <T> T setFieldByField(T object, String fieldName, Object value) {
        try {
            // 获取对象的Class
            Class<?> clazz = object.getClass();
            // 获取Field
            Field field = clazz.getDeclaredField(fieldName);
            // 设置可访问(private字段也可访问)
            field.setAccessible(true);
            // 赋值
            field.set(object, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
    /**
     * 使用Map批量赋值
     */
    public static <T> T setFieldsByMap(T object, Map<String, Object> fieldMap) {
        for (Map.Entry<String, Object> entry : fieldMap.entrySet()) {
            setFieldBySetter(object, entry.getKey(), entry.getValue());
        }
        return object;
    }
}

测试类

public class ReflectTest {
    public static void main(String[] args) {
        // 方法1:使用setter反射赋值
        testSetterReflect();
        System.out.println("========================");
        // 方法2:使用Field直接赋值
        testFieldReflect();
        System.out.println("========================");
        // 方法3:使用Map批量赋值
        testMapReflect();
    }
    // 方法1:通过setter反射赋值
    private static void testSetterReflect() {
        System.out.println("=== 通过setter反射赋值 ===");
        User user = new User();
        // 调用工具类赋值
        ReflectUtil.setFieldBySetter(user, "id", 1L);
        ReflectUtil.setFieldBySetter(user, "name", "张三");
        ReflectUtil.setFieldBySetter(user, "age", 25);
        ReflectUtil.setFieldBySetter(user, "email", "zhangsan@example.com");
        System.out.println("设置后的对象:" + user);
    }
    // 方法2:通过Field直接赋值
    private static void testFieldReflect() {
        System.out.println("=== 通过Field直接赋值 ===");
        User user = new User();
        // 调用工具类赋值
        try {
            ReflectUtil.setFieldByField(user, "id", 2L);
            ReflectUtil.setFieldByField(user, "name", "李四");
            ReflectUtil.setFieldByField(user, "age", 30);
            ReflectUtil.setFieldByField(user, "email", "lisi@example.com");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("设置后的对象:" + user);
    }
    // 方法3:使用Map批量赋值
    private static void testMapReflect() {
        System.out.println("=== 使用Map批量赋值 ===");
        User user = new User();
        // 准备数据
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("id", 3L);
        dataMap.put("name", "王五");
        dataMap.put("age", 28);
        dataMap.put("email", "wangwu@example.com");
        // 批量赋值
        ReflectUtil.setFieldsByMap(user, dataMap);
        System.out.println("设置后的对象:" + user);
    }
}

高级应用:对象属性拷贝

import java.lang.reflect.Field;
public class BeanCopyUtil {
    /**
     * 对象属性拷贝(支持不同类型间的相同属性名拷贝)
     */
    public static <T> T copyProperties(Object source, Class<T> targetClass) {
        try {
            // 创建目标对象实例
            T target = targetClass.getDeclaredConstructor().newInstance();
            // 获取源对象的所有字段
            Field[] sourceFields = source.getClass().getDeclaredFields();
            for (Field sourceField : sourceFields) {
                // 设置源对象字段可访问
                sourceField.setAccessible(true);
                try {
                    // 获取目标对象中同名字段
                    Field targetField = targetClass.getDeclaredField(sourceField.getName());
                    targetField.setAccessible(true);
                    // 获取源对象字段值
                    Object value = sourceField.get(source);
                    // 赋值给目标对象
                    targetField.set(target, value);
                } catch (NoSuchFieldException e) {
                    // 目标对象没有该字段,跳过
                    continue;
                }
            }
            return target;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

测试对象属性拷贝

public class BeanCopyTest {
    public static void main(String[] args) {
        // 创建源对象
        User user = new User();
        user.setId(1L);
        user.setName("测试用户");
        user.setAge(25);
        user.setEmail("test@example.com");
        // 拷贝到另一个User对象
        User userCopy = BeanCopyUtil.copyProperties(user, User.class);
        System.out.println("源对象:" + user);
        System.out.println("拷贝对象:" + userCopy);
    }
}

性能优化:缓存反射元数据

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
public class ReflectCacheUtil {
    // 缓存Method对象,提高性能
    private static final ConcurrentHashMap<String, Method> METHOD_CACHE = new ConcurrentHashMap<>();
    public static <T> T setFieldCached(T object, String fieldName, Object value) {
        try {
            Class<?> clazz = object.getClass();
            // 构建缓存key
            String cacheKey = clazz.getName() + "." + fieldName;
            // 从缓存获取或创建setter方法
            Method setter = METHOD_CACHE.computeIfAbsent(cacheKey, key -> {
                try {
                    String setterName = "set" + fieldName.substring(0, 1).toUpperCase() 
                                     + fieldName.substring(1);
                    return clazz.getMethod(setterName, value.getClass());
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException("找不到setter方法: " + key, e);
                }
            });
            // 调用setter方法
            setter.invoke(object, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
}

运行结果

=== 通过setter反射赋值 ===
设置后的对象:User{id=1, name='张三', age=25, email='zhangsan@example.com'}
========================
=== 通过Field直接赋值 ===
设置后的对象:User{id=2, name='李四', age=30, email='lisi@example.com'}
========================
=== 使用Map批量赋值 ===
设置后的对象:User{id=3, name='王五', age=28, email='wangwu@example.com'}

注意事项

  1. 访问权限:使用setAccessible(true)可以访问私有字段,但需要注意安全性
  2. 类型匹配:反射赋值时需要注意数据类型匹配
  3. 性能问题:反射操作相对较慢,可考虑缓存Method/Field对象
  4. 异常处理:反射操作会抛出多种异常,需要妥善处理
  5. JDK版本:JDK 17+可能需要添加--add-opens参数

这个案例展示了Java反射赋值的基本用法和高级应用,可以根据实际需求选择适合的赋值方式。

抱歉,评论功能暂时关闭!