复制任何类型的对象[重复]

Posted

技术标签:

【中文标题】复制任何类型的对象[重复]【英文标题】:Copy Object of Any Type [duplicate] 【发布时间】:2013-03-24 16:30:32 【问题描述】:

我有以下。

public static <T> T someMethod(T originalObject) 

    T modifiedObject = /* copy of original object (HOW DO YOU DO THIS?) */

    /* Some logic that modifies the object. */
    ...

    return modifiedObject; // without changing original Object


那么问题来了,如果您不知道 T 可能是什么类型,如何创建 T 类型的副本?

REVISION - 为了更清楚,我将粘贴我的代码。

public class ObjectMerger 

    public static <T> T merge(T original, T patch) throws IllegalArgumentException, IllegalAccessException 

        Object mergedObject = original // TODO: implement a way to copy original

        Field[] inheritedFields = patch.getClass().getFields();
        Field[] memberFields = patch.getClass().getDeclaredFields();
        Field[] allFields = (Field[]) ArrayUtils.addAll(inheritedFields, memberFields);

        for (Field field : allFields) 

            Boolean originalAccessibility = field.isAccessible();
            field.setAccessible(true);

            Object fieldValue = field.get(patch);

            if (fieldValue != null) 

                Boolean fieldIsFinal = Modifier.isFinal(field.getModifiers());

                if (!fieldIsFinal) 
                    field.set(mergedObject, fieldValue);
                

            

            field.setAccessible(originalAccessibility);

        

        return mergedObject;

    


注意:我曾尝试说 T 扩展 Cloneable,但这是不行的。我相信实现 Cloneable 并不能确保克隆是可见的。

注意:注意重复!

对于那些将其标记为重复的人,请阅读问题。这是在寻求一种方法来复制未知类型的对象。无论如何,据我所知,这是不可能的。感谢大家的意见。

【问题讨论】:

你要克隆对象吗? 您能否进一步解释一下您为什么要这样做?这样我们就可以向您建议一些正确的方法。 我修改了我的问题。我希望这让它更清楚一点。谢谢。 另一个思路:检查对象是否实现Serializable。如果是,则序列化然后反序列化为不同的对象。 【参考方案1】:

如果你完全不知道 T 是什么,你能做的最好的就是测试它是否实现了 Cloneable.clone()

if (originalObject implements Cloneable) 
  T modifiedObject = originalObject.clone();
  // ...
 else 
  throw new IllegalArgumentException();

你也可以限制T:

public static <T extends Cloneable> T someMethod(T originalObject) 
  T modifiedObject = originalObject.clone();

无论如何,你如何指望修改一个你完全不知道它是什么的对象?你的用例听起来有点奇怪。如果您描述您正在尝试做的事情(而不是如何您尝试这样做),可能会更容易提供帮助。

【讨论】:

我早些时候尝试过,但没有运气。我不相信实现 Cloneable 可以确保 clone 方法是可见的,编译器似乎也同意。不过你会想。我想要做的是通过检查字段使用反射合并任何类型的两个对象。实际上我已经创建了一个成功的方法,但我不想修改原来的。 合并两个对象是什么意思? 关于Cloneable.clone() 的知名度,你是对的。您可以尝试通过反射调用它,但这似乎非常不可靠。让我们看看您对合并两个对象有什么看法,也许我们可以找到一个好的解决方案。 基本上你有原始对象和补丁。它们都是同一类型。当您合并它们时,它会扫描补丁中所有字段的值。如果它不为空,则它会覆盖原始对同一字段的值。它对所有领域都这样做。因此,“修补或合并对象”。也许补丁会是一个更好的名字。 如果你真的完全无法控制你的方法应该处理的对象,那么就没有办法实现你想要的。如果我将ThreadSocketInputStream 的实例传递给您的方法怎么办?你真的应该限制你愿意处理的对象。【参考方案2】:

那么问题来了,如果您不知道T 可能是什么类型,如何创建T 类型的副本?

如果你真的不知道T 是什么,那你根本无法复制。

首先,没有用于复制对象的通用 API(任何给定类型可能支持也可能不支持 clone())。

但是,主要原因是T 可能根本不支持复制。例如,如果TFileInputStream 怎么办?你希望如何复制它的一个实例?

此外,如果您不知道T 是什么,您将如何实现/* Some logic that modifies the object. */

【讨论】:

没错,我觉得这个问题不太清楚【参考方案3】:

如果你准备好使用 XStream,这里是解决方案,

XStream xstream = new XStream();

return (T) xstream.fromXML(XSTREAM.toXML(originalObject));

【讨论】:

【参考方案4】:

正如标题所说的复制任何类型的对象,那么我认为您唯一的选择就是使用Reflection API。此外,即使您使用反射,您也需要根据创建副本的内容制定一些标准,例如要从源对象复制的属性等。

【讨论】:

【参考方案5】:

有两种选择:

使用 clone()Cloneable 已在其他答案中建议 如果您不想限制为 Cloneable,请使用使用反射的 deep/shallow clone library。 (不推荐,但仍然可以选择)。应注意对象支持复制。

【讨论】:

以上是关于复制任何类型的对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在java中深度复制对象。该对象可能是也可能不是可序列化的[重复]

如何在 Typescript 的对象文字中定义“任何”数组? [复制]

我如何检查对象的类型? [复制]

比较对象类型时 typeof 和 is 有啥区别? [复制]

redis的主从复制

如何在类型变量中创建任何类型的字典? [复制]