如何使用Reflection API对生成的最终类的对象进行深层复制

时间:2016-07-12 10:21:38

标签: java arrays reflection

我发现了一种有用的方法here
但它无法处理具有数组成员的类,例如。

public class Test {
    int [] arr = new int[2];
}

上述答案的完整代码
我没有尝试实例化新数组:

public static Object cloneObject(Object _obj) {
    try {
        // begin my changes
        Object copy = null;
        if (!_obj.getClass().isArray())
            copy = _obj.getClass().newInstance();
        else {
            int len = Array.getLength(_obj);
            Class type = _obj.getClass().getComponentType();
            // Next line fails with: Compiler(syntax) error
            // copy = (type.getClass()[])Array.newInstance(_obj.getClass(), len);
            // Next line fails with: "InstantiationException: int cannot be instantiated"
            // copy = _obj.getClass().getComponentType().newInstance();
            // how then?
        }
        // end my changes
        for (Field field : _obj.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            if (field.get(_obj) == 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(copy, field.get(_obj));
            else {
                Object child = field.get(_obj);
                if (child == _obj)
                    field.set(copy, copy);
                else
                    field.set(copy, cloneObject(field.get(_obj)));
            }
        }
        return copy;
    } catch (Exception _e){
        return null;
    }
}

甚至可以实现吗?

2 个答案:

答案 0 :(得分:1)

请注意,每个数组类型都有一个可以使用的克隆方法,如

int[] array={ 1, 2, 3 }, copy=array.clone();

不幸的是,Reflection不会报告此方法,因此为了反射调用它,您必须查找Object.clone(),并且由于此基类'方法已声明为protected,因此可通过setAccessible(true)尽管数组的重写方法是public

此外,这只会创建一个浅的副本,因此在对象数组或多个维度的情况下,您必须递归地重复此步骤。但由于所有多维数组也是Object[]的子类型,因此可以统一处理它们:

if(_obj.getClass().isArray()) {
    Method cloneMethod = Object.class.getDeclaredMethod("clone");
    cloneMethod.setAccessible(true);
    copy=cloneMethod.invoke(_obj);
    if(copy instanceof Object[]) {
        Object[] array=(Object[])copy;
        for (int ix = 0; ix < array.length; ix++)
            array[ix]=cloneObject(array[ix]);
    }
    return copy;
}

答案 1 :(得分:0)

您不需要强制转换Array.newInstance方法返回的数组,因为您将它分配给类型为Object的变量(它将接受任何对象,并且数组也是对象)

只是做:

copy = Array.newInstance(type, len);