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中创建树型对象? [复制]

为啥 Java/JVM 实现选择 HEAP 数据结构在内存中存储对象? [复制]

连接字符串对象列表的最佳方法? [复制]

Javascript:将数组转换为对象的最佳方法是啥? [复制]

Qt 如何删除对象?存储 QObject 的最佳方式是啥? [复制]

Java中,复制一个对象,有啥好的方法