【问题标题】: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。如果是,则序列化然后反序列化为不同的对象。

标签: java copy clone


【解决方案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。 (不推荐,但仍然可以选择)。应注意对象支持复制。

      【讨论】:

        猜你喜欢
        • 2018-05-28
        • 2020-04-27
        • 2018-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-09
        相关资源
        最近更新 更多