4

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.

1 Answer 1

2

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;
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

will not work in case the class has no no-args constructor

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.