利用Java反射拷贝对象与集合容器中保存的对象

案例1

自定义一个类,在类中定义一个工具方法,这个工具方法可以针对任意的对象(通用性)数据进行拷贝。

package com.reflection.test;

public class Student {
    private String name;
    private int age;
    public String address;


    public Student() {
    }

    public Student(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
package com.reflection.test;

public class Teacher {
    private String tName;
    private int tAge;
    public String tAddress;

    public Teacher() {
    }

    public Teacher(String tName, int tAge, String tAddress) {
        this.tName = tName;
        this.tAge = tAge;
        this.tAddress = tAddress;
    }

    public String gettName() {
        return tName;
    }

    public void settName(String tName) {
        this.tName = tName;
    }

    public int gettAge() {
        return tAge;
    }

    public void settAge(int tAge) {
        this.tAge = tAge;
    }

    public String gettAddress() {
        return tAddress;
    }

    public void settAddress(String tAddress) {
        this.tAddress = tAddress;
    }
}
package com.reflection.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ObjectUtils {

    public static void main(String[] args) throws Exception {
        Student student = new Student("张无忌", 88, "西安");
        System.out.println(student);
        System.out.println(copyObject(student));
        
        // teach类不符合标准的javabean的规范
        Teacher teacher = new Teacher("张无忌", 88, "西安");
        System.out.println(teacher);
        System.out.println(copyObjectImproved(teacher));

    }

    /**
     * 对象的拷贝
     *
     * @param srcObj
     * @return
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static Object copyObject(Object srcObj) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 1. 通过对象名.getClass()方法获得
        Class<?> srcClass = srcObj.getClass();
        // 2.依据源对象新建一个全新的对象用来进行返回
        // Constructor对象反映了由该 Class对象表示的类的所有公共构造函数
        Constructor<?> constructor = srcClass.getConstructor();
        //  T newInstance(Object... initargs) 使用由此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例
        Object copyObject = constructor.newInstance();
        // 3. 依据源对象获取源对象中所有的属性
        // Field[] getDeclaredFields() 返回一个 Field对象的数组,反映了由该 Class对象表示的类或接口声明的所有字段
        Field[] srcFields = srcClass.getDeclaredFields();
        // 4.循环遍历,将源对象的属性赋值到新的对象上面
        for (int i = 0; i < srcFields.length; i++) {
            // 我们使用下属的方式打印出的格式如下:private java.lang.String com.reflection.Student.name
            // 我们只需要属性名称即可
            // System.out.println(srcFields[i]);
            String srcFieldName = srcFields[i].getName();
            // 获取方法中的参数类型
            Class<?> srcFieldtype = srcFields[i].getType();
            // System.out.println(srcFieldtype);
            // 输出的格式如下:name
            // System.out.println(srcFieldName);
            // 在一个标准的JavaBean中一个会有get/set方法,我们从get方法中获取构造参数中的值,格式如下:getAge|setAge
            // 所以得到的属性名的第一个首字母应该将其变成大写
            String upperCase = srcFieldName.substring(0, 1).toUpperCase();
            // 截取除首字母以外的属性的其他部分
            String substring = srcFieldName.substring(1);
            // 我们将与get拼接起来得到一个完整的的get方法名
            String getMethod = "get" + upperCase + substring;
            // Method getMethod(String name, Class<?>... parameterTypes) 返回一个 方法对象,该对象反映由该 Class对象表示的类或接口的指定公共成员方法
            Method srcClassMethod = srcClass.getMethod(getMethod);
            // 在类或接口上提供有关单一方法的信息和访问权限
            // Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法
            // Object:返回值类型
            // obj:调用方法的对象
            // args:方法需要的参数
            Object object_value = srcClassMethod.invoke(srcObj);
            // 使用的同样的方式获取set方法
            String setMethodName = "set" + upperCase + substring;
            Method setMethod = srcClass.getMethod(setMethodName, srcFieldtype);
            // 我们为新的对象赋值
            setMethod.invoke(copyObject, object_value);
        }
        return copyObject;
    }

    /**
     * 对象的拷贝的升级与优化
     *
     * @param srcObj
     * @return
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static Object copyObjectImproved(Object srcObj) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> srcClass = srcObj.getClass();
        Constructor<?> constructor = srcClass.getConstructor();
        Object copyObject = constructor.newInstance();

        Field[] srcFields = srcClass.getDeclaredFields();

        for (Field field : srcFields) {
            String srcFieldName = field.getName();
            Class<?> srcFieldtype = field.getType();

            // 构建 get 方法名
            String getMethodName = "get" + capitalizeFirstLetter(srcFieldName);
            // 构建 set 方法名
            String setMethodName = "set" + capitalizeFirstLetter(srcFieldName);

            try {
                Method getMethod = srcClass.getMethod(getMethodName);
                Object value = getMethod.invoke(srcObj);

                Method setMethod = srcClass.getMethod(setMethodName, srcFieldtype);
                setMethod.invoke(copyObject, value);
            } catch (NoSuchMethodException e) {
                System.out.println("Method not found: " + e.getMessage());
                // 如果某个字段没有对应的 get 或 set 方法,可以选择跳过或进行其他处理
            }
        }
        return copyObject;
    }

    private static String capitalizeFirstLetter(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }


}

image-20240812231145002

案例2

给你提供一组数据信息,编写一个通用的方法实现将这些数据转换为一个集合容器中保存的对象。

提供数据格式及数据信息:

List<Map<String,Object>>  listMap = new  ArrayList<Map<String,Object>>();

Map<String,Object>  map1 = new  HashMap<String,Object>();
map1.put("id",1);
map1.put("name","张三");
map1.put("age",30);
map1.put("tel","110");

Map<String,Object>  map2 = new  HashMap<String,Object>();
map2.put("id",2);
map2.put("name","李四");
map2.put("age",25);
map2.put("tel","119");

Map<String,Object>  map3 = new  HashMap<String,Object>();
map3.put("id",3);
map3.put("name","王五");
map3.put("age",28);
map3.put("tel","120");

listMap.add(map1);
listMap.add(map2);
listMap.add(map3);

----- Person类 : id 、 name 、age 、tel 属性

编写一个方法,将List<Map<String,Object>> 类型 转换为 List 数据格式。

package com.reflection.test2;

/**
 * @Author: 史小创
 * @Time: 2024/8/12 下午2:39
 * @Description:
 */

public class Person {
    private Integer id;

    private String name;

    private Integer age;

    private String tel;


    public Person() {
    }


    public Person(Integer id, String name, Integer age, String tel) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.tel = tel;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer 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 getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", tel='" + tel + '\'' +
                '}';
    }
}
package com.reflection.test2;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public class ListMapToListObject<T> {
    public static void main(String[] args) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>();

        Map<String, Object> map1 = new HashMap<String, Object>();
        map1.put("id", 1);
        map1.put("name", "张三");
        map1.put("age", 30);
        map1.put("tel", "110");

        Map<String, Object> map2 = new HashMap<String, Object>();
        map2.put("id", 2);
        map2.put("name", "李四");
        map2.put("age", 25);
        map2.put("tel", "119");

        Map<String, Object> map3 = new HashMap<String, Object>();
        map3.put("id", 3);
        map3.put("name", "王五");
        map3.put("age", 28);
        map3.put("tel", "120");

        listMap.add(map1);
        listMap.add(map2);
        listMap.add(map3);


        ListMapToListObject<Person> listMapToListObject = new ListMapToListObject<>();
        List<Person> people = listMapToListObject.listMaptoListObject(Person.class, listMap);
        System.out.println(people);
    }

    public List<T> listMaptoListObject(Class<T> clas, List<Map<String, Object>> listMap) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        // 1.创建一个完整list集合用于返回
        List<T> list = new ArrayList<>();
        // 2.调用构造方法创建clas对象
        T clasObject = clas.newInstance();
        // 3.获取clas中所有的属性
        Field[] fields = clas.getDeclaredFields();
        // 4.循环遍历list集合中的map集合
        // 要求我们触底进来的这个集合不能为空
        if (!listMap.isEmpty() && listMap.size() > 0) {
            // 循环遍历list集合中的map集合
            // 在map集合中的key是我们类属性的属性名,value是我们的属性值
            for (Map<String, Object> map : listMap) {
                // 遍历所有的属性
                for (Field field : fields) {
                    // 属性名
                    String fieldName = field.getName();
                    // 属性类型
                    Class<?> fieldtype = field.getType();
                    // 构建 set 方法名
                    String setMethodName = "set" + capitalizeFirstLetter(fieldName);
                    // 构建set方法,返回类型
                    Method setMethod = clas.getDeclaredMethod(setMethodName, fieldtype);
                    // 获取map集合中相应的key的值
                    Object object_value = map.get(fieldName);
                    // 执行set方法
                    setMethod.invoke(clasObject, object_value);
                }
                list.add(clasObject);
            }
        }
        return list;
    }

    private static String capitalizeFirstLetter(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
}

image-20240812231503357

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值