考虑下面的代码:

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'

所以,我想把dumm复制到dum2,在不影响dum2的情况下改变dumm。但是上面的代码并没有这样做。当我改变了dumm中的一些东西,同样的变化也会发生在dum2中。

我想,当我说dumtwo = dum时,Java只复制了引用。那么,有没有办法创建一个新的dum副本并将其分配给dumtwo呢?


当前回答

使用深度克隆工具:

SomeObjectType copy = new Cloner().deepClone(someObject);

这将深度复制任何java对象,检查它在https://github.com/kostaskougios/cloning

其他回答

public class MyClass implements Cloneable {

private boolean myField= false;
// and other fields or objects

public MyClass (){}

@Override
public MyClass clone() throws CloneNotSupportedException {
   try
   {
       MyClass clonedMyClass = (MyClass)super.clone();
       // if you have custom object, then you need create a new one in here
       return clonedMyClass ;
   } catch (CloneNotSupportedException e) {
       e.printStackTrace();
       return new MyClass();
   }

  }
}

在你的代码中:

MyClass myClass = new MyClass();
// do some work with this object
MyClass clonedMyClass = myClass.clone();

您可以尝试实现Cloneable并使用clone()方法;但是,如果你使用clone方法,你应该——按照标准——总是覆盖Object的公共Object clone()方法。

在包中导入org.apache.commons.lang.SerializationUtils;有一种方法:

SerializationUtils.clone(Object);

例子:

this.myObjectCloned = SerializationUtils.clone(this.object);

使用Kotlin扩展函数

fun <T : Any?> T.duplicate(): T? {
    var copyObject: T? = null
    try {
        val byteArrayOutputStream = ByteArrayOutputStream()
        val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
        objectOutputStream.writeObject(this)
        objectOutputStream.flush()
        objectOutputStream.close()
        byteArrayOutputStream.close()
        val byteData = byteArrayOutputStream.toByteArray()
        val byteArrayInputStream = ByteArrayInputStream(byteData)
        try {
            copyObject = ObjectInputStream(byteArrayInputStream).readObject() as T
        } catch (e: ClassNotFoundException) {
            e.printStackTrace()
        }
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return copyObject
}

用例

var object = Any()
var duplicateObject = object.duplicate()

Java

<T extends Object> T copyObject(T sourceObject) {

    T copyObject = null;

    try {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(sourceObject);
        objectOutputStream.flush();
        objectOutputStream.close();
        byteArrayOutputStream.close();
        byte[] byteData = byteArrayOutputStream.toByteArray();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteData);
        try {
            copyObject = (T) new ObjectInputStream(byteArrayInputStream).readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return copyObject;
}

用例

Object object = new Object();
Object duplicateObject = copyObject(object);

==============================================

芬兰湾的科特林更新

如果您使用数据类,那么您将有复制方法来复制Kotlin数据类。很酷的是,你还可以通过一些值来修改对象的新副本。我推荐这种方式。

例子:

/ /类

data class TestModel(val title: String, var subtitle: String)

用例

val testClass = TestModel("Test title", "Test subtitle")

val newInstance = testClass.copy(subtitle = "new subtitle for copy instance")

除了显式复制,另一种方法是使对象不可变(没有set或其他mutator方法)。这样问题就不会出现了。对于较大的对象,不变性变得更加困难,但另一方面,它推动你朝着分裂成连贯的小对象和复合对象的方向发展。