复制任何类型的对象[重复]
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()
的知名度,你是对的。您可以尝试通过反射调用它,但这似乎非常不可靠。让我们看看您对合并两个对象有什么看法,也许我们可以找到一个好的解决方案。
基本上你有原始对象和补丁。它们都是同一类型。当您合并它们时,它会扫描补丁中所有字段的值。如果它不为空,则它会覆盖原始对同一字段的值。它对所有领域都这样做。因此,“修补或合并对象”。也许补丁会是一个更好的名字。
如果你真的完全无法控制你的方法应该处理的对象,那么就没有办法实现你想要的。如果我将Thread
、Socket
或InputStream
的实例传递给您的方法怎么办?你真的应该限制你愿意处理的对象。【参考方案2】:
那么问题来了,如果您不知道
T
可能是什么类型,如何创建T
类型的副本?
如果你真的不知道T
是什么,那你根本无法复制。
首先,没有用于复制对象的通用 API(任何给定类型可能支持也可能不支持 clone()
)。
但是,主要原因是T
可能根本不支持复制。例如,如果T
是FileInputStream
怎么办?你希望如何复制它的一个实例?
此外,如果您不知道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 的对象文字中定义“任何”数组? [复制]