Java 深拷贝工具类

工具类代码:

package com.example.demo.util;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * @author ssl
 * @date 2023/2/8 10:03
 */

public class CopyUtil {
    //V3
    public static  <T> T copyClassV3(Object source, Class<T> aClass){
        if (source == null){
            return null;
        }
        T t = null;
        try {
            Class<?> sourceClass = source.getClass();
            GetAll getAll = new GetAll<>(sourceClass).invoke();
            Field[] sourceFields = getAll.getFields();
            HashMap<String, Field> fieldHashMap = new HashMap<>();
            for (Field sourceField : sourceFields) {
                fieldHashMap.put(sourceField.getName(), sourceField);
            }
            getAll = new GetAll<T>(aClass).invoke();
            Field[] fields = getAll.getFields();
            Method[] methods = getAll.getMethods();

            t = aClass.newInstance();
            for (Field field : fields) {
                Field sourceField = fieldHashMap.get(field.getName());
                if (sourceField == null) {
                    continue;
                }else {
                    sourceField.setAccessible(true);
                    Object o = sourceField.get(source);
                    if (o == null && StringUtils.isBlank(String.valueOf(o))){
                        continue;
                    }
                }
                field.setAccessible(true);
                Class<?> type = field.getType();
                Object o = null;
                if (type.isPrimitive() || isBaseType(type)) {
                    o = sourceField.get(source);
                }else {
                    o = copyClassV3(sourceField.get(source), type);
                }
                String methodName = "set" + captureName(field.getName());
                Method declaredMethod = getSetMethod(methodName, methods);
                declaredMethod.invoke(t, o);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }
        return t;
    }


    //原始代码升级V2
    public static  <T> T copyClassConcise(Object source, Class<T> aClass){
        if (source == null){
            return null;
        }
        T t = null;
        try {
            Class<?> sourceClass = source.getClass();
            GetAll getAll = new GetAll<>(sourceClass).invoke();
            Field[] sourceFields = getAll.getFields();
            Method[] sourceMethods = getAll.getMethods();
//            Field[] sourceFields = sourceClass.getDeclaredFields();
            HashMap<String, Field> fieldHashMap = new HashMap<>();
            for (Field sourceField : sourceFields) {
                fieldHashMap.put(sourceField.getName(), sourceField);
            }
//            Field[] Fields = aClass.getDeclaredFields();
            getAll = new GetAll<T>(aClass).invoke();
            Field[] fields = getAll.getFields();
            Method[] methods = getAll.getMethods();

            t = aClass.newInstance();
            for (Field field : fields) {
                Field sourceField = fieldHashMap.get(field.getName());
                if (sourceField == null) {
                    continue;
                }else {
                    sourceField.setAccessible(true);
                    Object o = sourceField.get(source);
                    if (o == null && StringUtils.isBlank(String.valueOf(o))){
                        continue;
                    }
                }
                field.setAccessible(true);
                Class<?> type = field.getType();
                Object o = null;
                if (type.isPrimitive() || isBaseType(type)) {
                    o = sourceField.get(source);
                }else {
                    o = copyClassConcise(sourceField.get(source), type);
                }
                String methodName = "set" + captureName(field.getName());
                Method declaredMethod = getSetMethod(methodName, methods);
                declaredMethod.invoke(t, o);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }
        return t;
    }

    //根据方法名获得方法
    public static Method getSetMethod(String setMethodName, Method[] methods){
        for (Method method : methods) {
            String name = method.getName();
            if (setMethodName.equals(name)){
                return method;
            }
        }
        return null;
    }


    //原始代码V1
    public static  <T> T copyClass(Object source, Class<T> aClass){
        if (source == null){
            return null;
        }
        T t = null;
        try {
            Class<?> sourceClass = source.getClass();
            Field[] sourceFields = sourceClass.getDeclaredFields();
            HashMap<String, Field> fieldHashMap = new HashMap<>();
            for (Field sourceField : sourceFields) {
                fieldHashMap.put(sourceField.getName(), sourceField);
            }
            Field[] Fields = aClass.getDeclaredFields();
            t = aClass.newInstance();
            for (Field field : Fields) {
                Field sourceField = fieldHashMap.get(field.getName());
                sourceField.setAccessible(true);
                if (sourceField == null) {
                    continue;
                }else {
                    Object o = sourceField.get(source);
                    if (o == null && StringUtils.isBlank(String.valueOf(o))){
                        continue;
                    }
                }
                field.setAccessible(true);

                //方法二
                /*Type type = field.getGenericType();
                String methodName = "";
                if (field.getClass().isPrimitive() || isBaseType(type)) {
                    String typeName = type.getTypeName();
                    if (typeName.equals("java.lang.Boolean") || typeName.equals("boolean")){
                        methodName = "is" + captureName(field.getName());
                    }else {
                        methodName = "set" + captureName(field.getName());
                    }
                    Method declaredMethod = aClass.getDeclaredMethod(methodName, field.getType());
                    declaredMethod.invoke(t, sourceField.get(source));
                }else {
                    Object o = copyClass(sourceField.get(source), field.getType());
                    methodName = "set" + captureName(field.getName());
                    Method declaredMethod = aClass.getDeclaredMethod(methodName, field.getType());
                    declaredMethod.invoke(t, o);
                }*/

                //方法一
                Class<?> type = field.getType();
                String sourceMethodName = "";
                Object o = null;
                if (type.isPrimitive() || isBaseType(type)) {
                    /*String typeName = type.getName();
                    if (typeName.equals("java.lang.Boolean") || typeName.equals("boolean")){
                        sourceMethodName = "is" + captureName(sourceField.getName());
                    }else {
                        sourceMethodName = "get" + captureName(sourceField.getName());
                    }
                    Method sourceClassDeclaredMethod = sourceClass.getDeclaredMethod(sourceMethodName);
                    o = sourceClassDeclaredMethod.invoke(source);*/
                    o = sourceField.get(source);
                }else {
                    o = copyClass(sourceField.get(source), type);
                }
                String methodName = "set" + captureName(field.getName());
                Method declaredMethod = aClass.getDeclaredMethod(methodName, type);
                declaredMethod.invoke(t, o);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return t;
    }

    //首字母大写
    public static String captureName(String name) {
        char[] cs=name.toCharArray();
        cs[0]-=32;
        return String.valueOf(cs);
    }

    //判断是否是基本类型的包装类并且兼容泛式的类型
    public static boolean isBaseType(Class<?> type) {
        String className = type.getName();
        if (className.equals("java.lang.Integer") ||
                className.equals("java.lang.Byte") ||
                className.equals("java.lang.Long") ||
                className.equals("java.lang.Double") ||
                className.equals("java.lang.Float") ||
                className.equals("java.lang.Character") ||
                className.equals("java.lang.Short") ||
                className.equals("java.lang.String") ||
                className.equals("java.lang.Boolean") ||
                className.equals("java.lang.Object")) {
            return true;
        }
        return false;
    }

    private static class GetAll<T> {
        private Class<T> aClass;
        private Field[] fields;
        private Method[] methods;

        public GetAll(Class<T> aClass) {
            this.aClass = aClass;
        }

        public Field[] getFields() {
            return fields;
        }

        public Method[] getMethods() {
            return methods;
        }

        public GetAll invoke() {
            List<Field> fieldList = new ArrayList<>();
            List<Method> methodList = new ArrayList<>();
            Class clazz = aClass;
            while (clazz != Object.class){
                fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
                methodList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredMethods())));
                clazz = clazz.getSuperclass();
            }
            fields = new Field[fieldList.size()];
            methods = new Method[methodList.size()];
            fieldList.toArray(fields);
            methodList.toArray(methods);
            return this;
        }
    }


    /*public static boolean isBaseType(Type type) {
        String className = String.valueOf(type);
        if (className.contains("java.lang.Integer") ||
                className.contains("java.lang.Byte") ||
                className.contains("java.lang.Long") ||
                className.contains("java.lang.Double") ||
                className.contains("java.lang.Float") ||
                className.contains("java.lang.Character") ||
                className.contains("java.lang.Short") ||
                className.contains("java.lang.String") ||
                className.contains("java.lang.Boolean")) {
            return true;
        }
        return false;
    }*/


}

测试代码:

package com.example.demo.test;

import com.example.demo.entity.*;
import com.example.demo.util.CopyUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;

/**
 * @author ssl
 * @date 2023/2/8 10:51
 */

public class CopyTest {
    public static void main(String[] args) {
        copyTest4();
    }
    public static void copyTest4(){
        User3 u1 = new User3();
        u1.setId(1L);
        u1.setName("小明");
        u1.setAge(12);
        u1.setB(true);
        u1.setPointXY(new PointXY("12", "13"));
        Notepad<String, String> notepad = new Notepad<>();
        notepad.setKey("key");
        notepad.setValue("value");
        u1.setNotepad(notepad);
        User3 user = CopyUtil.copyClassV3(u1, User3.class);
        System.out.println(u1);
        System.out.println(user);
        System.out.println("=====");
        user.getNotepad().setKey("test");
        user.getPointXY().setX("11");
        user.setAge(11);
        user.setName("小红");
        System.out.println(u1);
        System.out.println(user);

        //其他拷贝类工具
        User3 u2 = new User3();
        BeanUtils.copyProperties(u1, u2);
        System.out.println("-----");
        System.out.println(u2);
        u2.getNotepad().setKey("test");
        u2.getPointXY().setX("11");
        u2.setAge(11);
        u2.setName("小红");
        System.out.println(u1);
        System.out.println(u2);
        
        //其他拷贝类工具
        System.out.println("**********");
        System.out.println(u1);
        ObjectMapper objectMapper = new ObjectMapper();
        User3 u3 = null;
        try {
            u3 = objectMapper.readValue(objectMapper.writeValueAsString(u1), User3.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(u3);
        u3.getNotepad().setKey("test2");
        u3.getPointXY().setX("111");
        u3.setAge(112);
        u3.setName("小天");
        System.out.println(u1);
        System.out.println(u3);
    }


    public static void copyTest3(){
        Notepad<Object, Object> n1 = new Notepad<>();
        n1.setKey("key");
        n1.setValue("value");
        Notepad n2 = CopyUtil.copyClassConcise(n1, Notepad.class);
        System.out.println(n1);
        System.out.println(n2);
        System.out.println("------");
        n2.setKey("test");
        n2.setValue("testvalue");
        System.out.println(n1);
        System.out.println(n2);
    }

    public static void copyTest2(){
        User u1 = new User();
        u1.setId(1L);
        u1.setName("小明");
        u1.setAge(12);
        u1.setB(true);
        u1.setPointXY(new PointXY("12", "13"));
        Notepad<String, String> notepad = new Notepad<>();
        notepad.setKey("key");
        notepad.setValue("value");
        u1.setNotepad(notepad);
        User2 user = CopyUtil.copyClassConcise(u1, User2.class);
        System.out.println(u1);
        System.out.println(user);
        System.out.println("====");
        user.getNotepad().setKey("test");
        user.getPointXY().setX("11");
        user.setAge(11);
        user.setName("小红");
        System.out.println(u1);
        System.out.println(user);

        //其他拷贝类工具
        User u2 = new User();
        BeanUtils.copyProperties(u1, u2);
        System.out.println("-----");
        System.out.println(u2);
        u2.getNotepad().setKey("test");
        u2.getPointXY().setX("11");
        u2.setAge(11);
        u2.setName("小红");
        System.out.println(u1);
        System.out.println(u2);

        //其他拷贝类工具
        System.out.println("**********");
        System.out.println(u1);
        ObjectMapper objectMapper = new ObjectMapper();
        User2 u3 = null;
        try {
            u3 = objectMapper.readValue(objectMapper.writeValueAsString(u1), User2.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(u3);
        u3.getNotepad().setKey("test2");
        u3.getPointXY().setX("111");
        u3.setAge(112);
        u3.setName("小天");
        System.out.println(u1);
        System.out.println(u3);
    }

    public static void copyTest1(){
        User u1 = new User();
        u1.setId(1L);
        u1.setName("小明");
        u1.setAge(12);
        u1.setB(true);
        u1.setPointXY(new PointXY("12", "13"));
        Notepad<String, String> notepad = new Notepad<>();
        notepad.setKey("key");
        notepad.setValue("value");
        u1.setNotepad(notepad);
        User user = CopyUtil.copyClassConcise(u1, User.class);
        System.out.println(u1);
        System.out.println(user);
        System.out.println("====");
        user.getNotepad().setKey("test");
        user.getPointXY().setX("11");
        user.setAge(11);
        user.setName("小红");
        System.out.println(u1);
        System.out.println(user);

        //其他拷贝类工具
        User u2 = new User();
        BeanUtils.copyProperties(u1, u2);
        System.out.println("-----");
        System.out.println(u2);
        u2.getNotepad().setKey("test");
        u2.getPointXY().setX("11");
        u2.setAge(11);
        u2.setName("小红");
        System.out.println(u1);
        System.out.println(u2);

        //其他拷贝类工具
        System.out.println("**********");
        System.out.println(u1);
        ObjectMapper objectMapper = new ObjectMapper();
        User u3 = null;
        try {
            u3 = objectMapper.readValue(objectMapper.writeValueAsString(u1), User.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(u3);
        u3.getNotepad().setKey("test2");
        u3.getPointXY().setX("111");
        u3.setAge(112);
        u3.setName("小天");
        System.out.println(u1);
        System.out.println(u3);
    }
}

转载表明出处

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Java中实现深拷贝需要考虑到对象的序列化和反序列化,下面是一个使用Java序列化实现深拷贝工具类代码示例: ``` import java.io.*; public class DeepCopyUtil { public static <T extends Serializable> T deepCopy(T obj) throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (T) ois.readObject(); } } ``` 使用示例: ``` public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException { List<Integer> list1 = new ArrayList<>(); list1.add(1); list1.add(2); list1.add(3); List<Integer> list2 = DeepCopyUtil.deepCopy(list1); System.out.println("list1 == list2: " + (list1 == list2)); // false System.out.println("list1.equals(list2): " + list1.equals(list2)); // true } } ``` 该工具类使用了Java的序列化和反序列化,通过将对象序列化成字节数组,再反序列化成新的对象,从而实现了深拷贝。需要注意的是,被复制的对象必须是可序列化的。 ### 回答2: Java中的深拷贝工具类主要用于在创建对象副本时,将对象的所有属性值及其相关的对象也进行拷贝,从而保证新对象的独立性。实现深拷贝的常用方法有两种:序列化与反序列化、自定义深拷贝方法。 首先,使用序列化与反序列化可以实现深拷贝。通过将对象写入流并从流中读取,可以获得该对象的副本。首先,将对象写入OutputStream,再通过ByteArrayInputStream将流转化为字节数组。然后,通过ObjectInputStream将字节数组转化为对象并返回。 其次,可以自定义深拷贝方法。该方法通过递归遍历对象的所有属性,对每个属性实施拷贝操作。如果属性为基本类型,则直接拷贝;如果为引用类型,则递归进行深拷贝。这样可以确保新对象的每个属性都是独立的。 需要注意的是,在使用自定义深拷贝方法时,需要手动实现所有需要拷贝的属性的拷贝逻辑。如果对象的属性过多或复杂,手动实现深拷贝可能会较为繁琐。 综上所述,Java中的深拷贝工具类可以通过序列化与反序列化或自定义深拷贝方法来实现。根据具体需求和对象属性的复杂程度,可以选择合适的方法来完成对象的深拷贝操作。 ### 回答3: Java深拷贝工具类是一个用于复制对象的工具类深拷贝的概念是指在复制对象时,不仅复制对象本身,还复制对象所引用的其他对象,从而实现完全独立的副本。 在实现深拷贝工具类时,可以通过以下步骤: 1. 首先,需要确保被复制的对象及其引用的对象都实现了Cloneable接口,这样才能使用Object类的clone()方法进行对象的浅拷贝。 2. 创建一个新的空对象,用于存储复制后的对象。 3. 遍历被复制的对象的所有引用类型属性或集合,并逐一进行深拷贝。 4. 对于引用类型属性,可以通过递归调用深拷贝方法,将引用对象复制到新的对象中。 5. 对于集合类型属性,可以创建一个新的集合对象,并将原集合中的每个元素进行深拷贝后添加到新的集合中。 6. 最终返回复制后的对象。 需要注意的是,深拷贝工具类只能完成基本数据类型和引用类型的深拷贝,对于对象内部的静态变量或其他逻辑复杂的情况,需要额外的处理方式。 总之,通过深拷贝工具类,我们可以实现对Java对象及其引用对象的完全独立复制,确保原对象和复制对象之间的数据隔离,适用于需要保护原有数据的场景,如多线程环境下的数据处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值