简体   繁体   中英

JAVA. Using reflection for deep copy object

I try to copy an object by reflection. I haven't difficulties with copy primitive types, but i dont understand how copy reference types.

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
public class ReflMethod {
    private static final Set<Class<?>> WRAPPER_TYPES = getWrapperTypes();

    public Object CopyObject(Object object) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        Class clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        Object instance =  object.getClass().newInstance();

        for(Field field : fields) {
            field.setAccessible(true);
            Class newClass = Class.forName(field.get(object).getClass().getName());
            if(isWrapperType(newClass)) {
                field.set(instance, field.get(object));
            }
            else if(!isWrapperType(newClass)) {

                //WEIRDNESS HERE
                field.set(instance, CopyObject(field.get(object).getClass().getName()));
                //WEIRDNESS HERE
            }
        }
        return instance;
    }

    public static boolean isWrapperType(Class<?> clazz)
    {
        return WRAPPER_TYPES.contains(clazz);
    }

    public static Set<Class<?>> getWrapperTypes()
    {
        Set<Class<?>> ret = new HashSet<Class<?>>();
        ret.add(Boolean.class);
        ret.add(Character.class);
        ret.add(Byte.class);
        ret.add(Short.class);
        ret.add(Integer.class);
        ret.add(Long.class);
        ret.add(Float.class);
        ret.add(Double.class);
        ret.add(Void.class);
        return ret;
    }
}

I want using recursion for copying reference types...Where do I think wrong?

public class Cat {
    private Phone phone;
    private int age;

    public Cat() {

    }

    public Cat(int age, Phone phone) {
        this.age = age;
        this.phone = phone;
    }

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Phone getPhone() {
        return phone;
    }
    public void setPhone(Phone phone) {
        this.phone = phone;
    }
}
public class Phone {
    private String name;
    public Phone() {

    }
    public Phone(String name) {
        this.name = name;
    }
    public void SetName(String name) {
        this.name = name;
    }
    public String GetName() {
        return name;
    }
}

And main class:

public class MainClass {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException {

        ReflMethod reflMethod = new ReflMethod();

        Phone phone1 = new Phone("IPhone");
        Cat cat1 = new Cat(20, phone1);
        Cat cat2 = (Cat)reflMethod.CopyObject(cat1);

        System.out.println("cat1 : " + cat1.getAge() + " " + cat1.getPhone().GetName());
        System.out.println("cat2 : " + cat2.getAge() + " " + cat2.getPhone().GetName());
        cat1.setAge(100);
        Phone phone = new Phone("Af");
        cat1.setPhone(phone);
        System.out.println("cat1 : " + cat1.getAge() + " " + cat1.getPhone().GetName());
        System.out.println("cat2 : " + cat2.getAge() + " " + cat2.getPhone().GetName());
    }
}

The code doesn't work because of the code marked as WEIRDNESS HERE.

The answer was found in the depths of Stackoverflow :D

But it doesn't work with collections :(

ReflMethod:

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class ReflMethod {


    public static Object CopyObject(Object object)
    {
        try
        {
            Object clone = object.getClass().newInstance();

            for(Field field : object.getClass().getDeclaredFields()) {
                field.setAccessible(true);

                if(field.get(object) == null || Modifier.isFinal(field.getModifiers()))
                {
                    continue;
                }

                if(field.getType().isPrimitive()
                        || field.getType().equals(String.class)
                        || field.getType().getSuperclass().equals(Number.class)
                        || field.getType().equals(Boolean.class))
                {
                    field.set(clone, field.get(object));
                }
                else {
                    Object childObj = field.get(object);
                    if(childObj == object) {
                        field.set(clone,clone);
                    }
                    else {
                        field.set(clone,CopyObject(field.get(object)));
                    }
                }
            }
            return clone;
        }
        catch (Exception e) {
            return  null;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM