Java 对象复制的最佳选择? [复制]
Posted
技术标签:
【中文标题】Java 对象复制的最佳选择? [复制]【英文标题】:Java object copy best option? [duplicate] 【发布时间】:2011-03-09 20:24:00 【问题描述】:可能重复:How do I copy an object in Java?
我需要在 Java 中复制一个对象(即“按值而不是按引用”复制对象,以便新对象不仅仅是对旧对象的引用)。我厌倦了实现可克隆并且更喜欢使用复制构造函数。但是,我需要复制的类有许多需要复制的成员变量(超过 100 个),因此向该类添加一个新的构造函数只是为了复制(仅在我的应用程序的一部分中需要)似乎是一个糟糕的解决方案由于它的长度很大。
有没有更好的解决方案?我应该只使用克隆()吗?我可以创建一个复制构造函数,但不是将所有字段一一复制,我可以反思吗?谢谢。
我基本上只需要创建一个与旧对象相同的新对象,但更改了一些(大约 100 个中的 10 个)字段(但我仍然需要两个对象..所以新对象不能是参考旧的)。我愿意接受任何建议。
【问题讨论】:
你真的需要100个成员变量吗?也许 Map 或 List 会做得更好。 是的,该类代表我的一个数据库表的列。您是对的,可能有更好的解决方案,但是这个类已经深深地绑定到一个大型应用程序中。我只需要添加复制功能。 超过 100 列!?该死,这超出了我想象的最糟糕的情况! 仅仅因为它是嵌入的并不意味着它是不可修改的。这就是您使用 OOP 的原因。也许其中一些成员变量可以组合到容器类中以便更好地管理,特别是如果它们可以在其他地方使用。此外,也许您的 DBA 应该研究规范化。如果你有 100 列,我向你保证有很多可以标准化的重复数据。一旦规范化,应该很容易将其分解为更有用、可重用的类,每个类都可以轻松拥有自己的复制构造函数或其他复制机制。 【参考方案1】:clone()
进行浅层克隆 - 它仅复制第一级字段。您应该避免使用clone()
和Cloneable
,因为它很难正确实现,而且很可能会出现问题,尽管不是立即可见。请参阅 what Joshua Bloch 对此的说明。
如果您想要深拷贝 - 即克隆整个对象层次结构,我可以建议两个选项:
如果您的对象实现了Serializable
,请使用SerializationUtils.clone(..)
(来自commons-lang)
如果它不能序列化,那么试试java deep cloning library
但是,如果您想要浅拷贝 - 即您仍然希望将所有字段复制到一个新对象,但是字段和字段的字段(等等)指向它们的原始值,那么您可以使用 @987654325 @(来自commons-beanutils)
除了克隆问题 - 拥有 100 个成员变量并不是一个好兆头。考虑将您的类拆分为多个类(更新:和多个表,使用外键。当然,如果适用的话。如果这些确实是同一个对象的属性,那么很好)
【讨论】:
我从帖子中删除了“深度克隆”一词,因为我认为这不是我的意思。我只需要复制成员变量。 好吧,那么我对浅拷贝的建议成立;) clone() 按预期工作。我想我需要重新审视为什么如此推荐反对。 @aeq - 不,不要使用克隆。查看我的更新 SerializationUtils.clone(..) 是完美的......谢谢【参考方案2】:一个选项可以是使用序列化。它不是最快的,但可能是最安全的之一。看this网站上的代码:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectputStream;
import java.io.ObjectOutputStream;
public class DeepObjectCopy
public static Object clone(Object copyObject)
try
ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(copyObject);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectputStream ois = new ObjectputStream(bais);
Object deepCopy = ois.readObject();
return deepCopy;
catch (IOException e)
e.printStackTrace();
catch(ClassNotFoundException e)
e.printStackTrace();
return null;
【讨论】:
我原则上赞成这一点,但我在主要问题中的评论是最重要的部分! glowcoder,你的问题是对的,但我不知道他的整个项目,所以我不想质疑他的意图。 好吧,我的回答中建议的 SerializationUtils 正是这样做的,但只有一行。【参考方案3】:BeanUtils
方法基于反射,因此它们(相对)慢。 dozer 和其他类似工具也是如此。复制构造函数是完成任务的最快方式,因此如果您不是为 Android 等平台编写代码,而每个 kb 代码都是一个问题,那么您应该选择这种方式。如果唯一的问题是编写复制构造函数,您可以使用 Eclipse 插件,例如 JUtils。
【讨论】:
以上是关于Java 对象复制的最佳选择? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Java/JVM 实现选择 HEAP 数据结构在内存中存储对象? [复制]
Javascript:将数组转换为对象的最佳方法是啥? [复制]