Java:传递“this”的副本? [复制]

Posted

技术标签:

【中文标题】Java:传递“this”的副本? [复制]【英文标题】:Java: pass in copy of "this"? [duplicate] 【发布时间】:2012-01-18 21:32:43 【问题描述】:

可能重复:How do I copy an object in Java?

我的类Claus 中有一个函数,它调用一个函数来接受类型Claus。我目前正在传递this 作为参数,但是它正在编辑我不希望它做的类的当前实例。相反,我希望它克隆类的当前实例并对其进行编辑,保持副本分开。我该怎么做?

编辑

也许我应该进一步澄清我的问题......

我有一个在另一个对象内的对象.. 例如Clausfloss。我一直在阅读shallow copydeep copy,我认为我的Claus 复制正确。我就是这么干的……

public Claus(Claus g)
    cla = new Floss(g.getFloss());
            //irrelevant other variables...
    p = g.getP();
    c = g.getC();

但是,Claus 中的函数我在构造函数中声明的方式完全相同.. 就是....

 cla = new Floss(g.getFloss());

其中 cla = Floss 变量和 g = Claus 正在传递给构造函数。 Floss 对象似乎并没有像它应该那样创建深层副本。为什么会这样?

【问题讨论】:

你能提供代码来说明你在做什么吗? Dose Claus 实现 Cloneable?如果你传入一个克隆怎么办?您的描述本身并没有难闻的代码气味,但可能有一种非常轻微的气味。我想知道你是不是搞错了。也许你最好告诉我们你想要实现什么行为,而不是你如何在代码中尝试实现它。 伙计,这里就像是克隆人的攻击。 我提供了有关我的问题的更新以帮助澄清问题。 “Floss 对象似乎没有像它应该的那样创建深层副本。”您能否提供更多详细信息,您有什么证据表明它没有正确地制作深拷贝? 【参考方案1】:

实现Cloneable 并使用this.clone(),就像任何其他变量一样。

【讨论】:

【参考方案2】:

你应该看看 Object#clone 方法

http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29

【讨论】:

+1 教我一些东西 :)【参考方案3】:

考虑为您的班级实施copy constructor。这是一个构造函数,它接受另一个相同类型的实例并将其状态复制到新对象中。

【讨论】:

【参考方案4】:
void foo(Claus c)


不是foo(this),而是foo(new Claus(this))

编辑:

然后像这样在Claus中定义一个拷贝构造函数:

public Claus(Claus c)

    this.whatever = c.whatever;
    // etc.

【讨论】:

我不认为Claus的构造函数会是这个样子。 在 Java 中复制构造函数? Java 中的这种风格很糟糕吗?抱歉,我有 C++ 背景,但很想了解 Java 标准。 Java 中没有内置的复制构造函数 内置啊。我不知道这一点,并补充说他应该定义自己的。谢谢你的提示!定义自己的复制 ctor 而不是使用克隆是否被认为是不好的风格?【参考方案5】:
 Object objClone = obj.clone();

克隆将返回,就像听起来一样,是您的对象的克隆。 Clone() 是 Object 超类的一个方法,所以如果你实现了 Cloneable 接口,你所有的对象都可以访问这个方法。

【讨论】:

仅当obj 的类型实现Cloneable 时才有效。否则你会得到CloneNotSupportedException【参考方案6】:

你可以这样做:

public class MyObject 
    //attributes
   private String attr1;

   public MyObject()  //first construct

   public MyObject(MyObject obj)  
       //do copy of all attributes 
       this.attr1 = obj.getAttr1();
   

   //setters and getters

   public void method(MyObject obj) 
      MyObject obj2 = new MyObject(obj);
      //your processing
   


然后调用它

MyObject obj = new MyObject();
obj.setAttr1("someone");
obj.method(obj);

希望对您有所帮助..

【讨论】:

【参考方案7】:

您可能想要实现.clone() 方法。但是,您必须确保它实现了Cloneable 接口。

但建议首选其他方法,例如 Copy Constructorstatic-factory-method,它们将对象作为参数并创建一个新实例,该实例是传递对象。

但是,您真正需要注意的一件事是,只是所有字段的副本就足够了,还是需要副本。因为,如果您需要深拷贝并创建对象的浅拷贝,则可能意味着代码中存在潜在的错误

【讨论】:

【参考方案8】:

正如其他人所说,您应该实现clone() 方法或创建一个复制构造函数。

无论您选择哪种解决方案,您都需要制作所谓的“深拷贝”。如果对象很简单,那么创建深层副本就很简单。如果对象很复杂,一个技巧是序列化和反序列化对象。这将以最少的工作量进行深层复制。

每当我这样做时,我都喜欢使用XStream 而不是本机Java 序列化。它将对象序列化为 XML,包括任何嵌套的对象和集合,然后您可以对其进行反序列化以获得深层副本。以下代码很可能适用于您的课程,无需修改:

public Claus clone(Claus source) 
      XStream xstream = new XStream();
      String serializedObj = xstream.toXML(source);
      return (Claus) xstream.fromXML(serializedObj);
   

【讨论】:

以上是关于Java:传递“this”的副本? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

C# 是通过引用还是作为副本将 List<T> 传递给方法? [复制]

通过副本或参考传递?

如何在排序之前保存数组的副本? [复制]

java常见问题

结构中的快速类在分配期间是不是通过副本传递?

将“this”传递给新对象的内联重写方法的正确方法是啥? [复制]