JAVA不同类相同属性的赋值(伪深度克隆)

本文介绍了一种跨类克隆机制,通过定义一个抽象基类Entity,并实现Cloneable接口,不仅可以实现同一类间的克隆,还能将一个类的实例克隆到另一个具有相同属性的不同类中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于浅克隆与深克隆网上都有很多代码,但克隆的是相同类型的类,那么如果两个类是不同的类,而属性的值又是一样的该怎么赋值呢!
我们可以定义一个父类Entity(名字随便你们怎么定义),实现Cloneable接口,重写clone()方法 ,用于相同类的克隆,再定义一个cloneTo(Class clazz)方法就可以赋值给另外一个类了,具体看代码:


package com.aiitec.test;


import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;


public abstract class Entity implements Cloneable {


    private int id;


    public int getId() {
        return id;
    }


    public void setId(int id) {
        this.id = id;
    }


    /**
     * 对象的克隆方法, 伪深度克隆,也就是说对象里的除常用数据类型外的属性都是 Entity的子类就没问题,
     * 但是StringBuffer,HashMap这些东西就不行了
     */
    @SuppressWarnings("unchecked")
    @Override
    public Object clone() {
        try {
            Object entity = super.clone();
            for (Field field : getClass().getDeclaredFields()) {
                field.setAccessible(true);
                try {
                    if( field.get(this) != null){
                        // 对象
                        if (Entity.class.isAssignableFrom(field.getType())) {
                            Object value = field.get(this);
                            field.set(this, ((Entity) value).clone());
                        } else if (List.class.isAssignableFrom(field.getType())) {
                            List<Object> datas = new ArrayList<>();
                            for (Object childEntity: (List<Object>)field.get(entity)) {
                                if(Entity.class.isAssignableFrom(childEntity.getClass())){
                                    datas.add(((Entity)childEntity).clone());                                       
                                } else {
                                    datas.add(childEntity);                                     
                                }
                            }
                            field.set(this, datas);
                        }                       
                    }
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return entity;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return null;
    }



    /**
     * 两个相同属性的类的克隆 比如 Data1 和 Data2的属性完全一样,那么就可以这样 Data2 data2 =
     * data1.cloneTo(Data2.class) 当然这里考虑的常用的数据类型 和
     * 继承至这个类的对象,特殊的数据类型可能不支持,但是已经达到我的要求了 这个最好写在一个所有对象的父类里,要不然又有其他问题
     * 
     * 同类克隆用clone()方法, 不同类克隆用cloneTo(Class<?>)方法
     * @param clazz
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    @SuppressWarnings("unchecked")
    public <T> T cloneTo(Class<T> clazz) {
        T newObj = null;
        try {
            Object entity = super.clone();
            if (entity.getClass().equals(clazz)) {
                newObj = (T) entity;
            } else {
                try {
                    newObj = clazz.newInstance();
                    //已经有值的类的所有属性
                    List<Field> fields = FieldUtil.getAllFields(getClass());
                    for (Field field : fields) {
                        field.setAccessible(true);
                        //等待赋值的类的所有属性
                        List<Field> field2s = FieldUtil.getAllFields(clazz);
                        for (Field field2 : field2s) {
                            if (field2.getName().equals(field.getName())) {
                                field2.setAccessible(true);
                                if(field.get(entity) != null){
                                    // Entity是当前类,也就是所有能互相复制的父类
                                    if (Entity.class.isAssignableFrom(field.getType())) {
                                        Entity child = (Entity) field.get(entity);
                                        field2.set(newObj, child.cloneTo(field2.getType()));                                        
                                    } else if (List.class.isAssignableFrom(field.getType())) {
                                        List<Object> datas = new ArrayList<>();
                                        for (Object childEntity: (List<Object>)field.get(entity)) {
                                            if(Entity.class.isAssignableFrom(childEntity.getClass())){
                                                datas.add(((Entity)childEntity).clone());                                       
                                            } else {
                                                datas.add(childEntity);                                     
                                            }
                                        }

                                        field2.set(newObj, datas);
                                    } else {
                                        field2.set(newObj, field.get(entity));
                                    }
                                }
                            }
                        }
                    }
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return newObj;
    }



    @Override
    public String toString() {


        StringBuilder sb = new StringBuilder();
        sb.append("{");
        List<Field> fields = FieldUtil.getAllFields(getClass());
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(this);
                sb.append('\"').append(field.getName()).append("\":");
                if (field.getType().isPrimitive()
                        || field.getType() == String.class || Enum.class.isAssignableFrom(field.getType())) {
                    sb.append('\"').append(value.toString()).append('\"')
                            .append(',');
                } else if (List.class.isAssignableFrom(field.getType())) {
                    List<?> datas = (List<?>) value;
                    sb.append('[');
                    for (int i = 0; i < datas.size(); i++) {
                        sb.append(datas.get(i).toString()).append(',');
                    }
                    if (sb.toString().endsWith(",")) {
                        sb.deleteCharAt(sb.length() - 1);
                    }
                    sb.append(']').append(',');
                } 
                else {// 对象的值不需要引号
                    sb.append(value.toString()).append(',');
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        if (sb.toString().endsWith(",")) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.append("}");
        return sb.toString();
    }
}
//再写一个类测试
public class test1 {


    public static void main(String[] args) {

        User user = new User();
        user.setId(5);
        user.setAge(18);
        user.setMoney(23.5f);
        user.setName("张三");
        Address address = new Address();
        address.setCity("广州");
        address.setStreet("荔湾路");
        user.setAddress(address);
        List<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        List<Image> images = new ArrayList<>();
        Image image = new Image();
        image.setPath("1.jpg");
        images.add(image);
        user.setIds(ids);
        user.setImages(images);


        User2 user2 = (User2)user.cloneTo(User2.class);
        user2.setAge(23);
        user2.setId(24);
        Address address2 = user2.getAddress();
        address2.setCity("北京");
        address2.setStreet("中关村");
        user2.setAddress(address2);

        Image image2 = new Image();
        image2.setPath("2.jpg");
        user2.getImages().add(image2);
        user2.getIds().add(666);

        user2.setCacheMode(Character.EXTROVERSION);
        System.out.println("child1:----"+user.toString());
        System.out.println("child4:----"+user2.toString());
    }
}
//打印结果,我格式化了
//child1:----
{
    "name": "张三",
    "age": "18",
    "money": "23.5",
    "cacheMode": "INTROVERT",
    "address": {
        "city": "广州",
        "street": "荔湾路",
        "id": "0"
    },
    "ids": [
        1,
        2,
        3
    ],
    "images": [
        {
            "path": "1.jpg",
            "id": "0"
        }
    ],
    "id": "5"
}
//child4:----
{
    "name": "张三",
    "age": "23",
    "money": "23.5",
    "cacheMode": "EXTROVERSION",
    "address": {
        "city": "北京",
        "street": "中关村",
        "id": "0"
    },
    "ids": [
        1,
        2,
        3,
        666
    ],
    "images": [
        {
            "path": "1.jpg",
            "id": "0"
        },
        {
            "path": "2.jpg",
            "id": "0"
        }
    ],
    "id": "24"
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值