如何在Java中复制对象?
考虑以下代码:如何在Java中复制对象?,java,object,copy,clone,Java,Object,Copy,Clone,考虑以下代码: 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
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'
因此,我想将dum
复制到dumtoo
并在不影响dumtoo
的情况下更改dum
。但上面的代码并没有这样做。当我在dum
中更改某些内容时,在dumtoo
中也会发生相同的更改
我猜,当我说
dumtwo=dum
时,Java只复制引用。那么,有没有办法创建dum
的新副本并将其分配给dumtwo
?要做到这一点,您必须以某种方式克隆对象。尽管Java有一种克隆机制,但如果不需要,就不要使用它。创建一个为您执行复制工作的复制方法,然后执行以下操作:
dumtwo = dum.copy();
这是一些关于复制不同技巧的更多建议。是的。您需要保存您的对象。如果您最终需要克隆(),这里有一个不错的解释
创建一个复制构造函数:
class DummyBean {
private String dummy;
public DummyBean(DummyBean another) {
this.dummy = another.dummy; // you can access
}
}
每个对象都有一个克隆方法,可以用来复制对象,但不要使用它。创建类和执行不正确的克隆方法太容易了。如果你要这么做,至少要读一读约书亚·布洛赫在书中对它所说的话。是的,你只是在引用这个对象。如果对象实现了
Cloneable
,则可以克隆该对象
查看这篇关于复制对象的wiki文章
除了显式复制,另一种方法是使对象不可变(no
set
或其他mutator方法)。这样,问题就永远不会出现。对于较大的对象,不变性变得更加困难,但另一方面,它将您推向分裂成连贯的小对象和组合的方向。您可以尝试实现Cloneable
并使用clone()
方法;但是,如果使用克隆方法,按照标准,您应该始终覆盖对象的公共对象克隆()
方法。如下所示:
public class Deletable implements Cloneable{
private String str;
public Deletable(){
}
public void setStr(String str){
this.str = str;
}
public void display(){
System.out.println("The String is "+str);
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class DummyBean implements Cloneable {
private String dummy;
public void setDummy(String dummy) {
this.dummy = dummy;
}
public String getDummy() {
return dummy;
}
@Override
public Object clone() throws CloneNotSupportedException {
DummyBean cloned = (DummyBean)super.clone();
cloned.setDummy(cloned.getDummy());
// the above is applicable in case of primitive member types like String
// however, in case of non primitive types
// cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
return cloned;
}
}
无论您想在哪里获得另一个对象,都可以执行简单的克隆。
e、 g:
您可以使用XStream从以下位置自动进行深度复制:
XStream是一个简单的库,用于将对象序列化为XML并返回
再说一遍
将其添加到项目中(如果使用maven)
这样,您就可以获得一个拷贝,而无需实现任何克隆接口。使用深度克隆实用程序:
SomeObjectType copy = new Cloner().deepClone(someObject);
这将深度复制任何java对象,请在基本:java中的对象复制中查看它。
让我们假设一个对象-obj1
,它包含两个对象,containedObj1和containedObj2
浅层复制:
浅层复制创建同一类的新的实例
,并将所有字段复制到新实例并返回它对象类提供了一个克隆
方法,并支持浅层复制。
深度复制:
当对象与其引用的对象一起复制时,会发生深度复制。下图显示了对obj1执行深度复制后的obj1
。不仅复制了obj1
,而且还复制了其中包含的对象。我们可以使用Java对象序列化
制作深度拷贝。不幸的是,这种方法也有一些问题()
可能的问题:
克隆
很难正确实施。
最好使用(如@egaga reply)或。
如果您有一个对象,您知道它有一个publicclone()
方法,但在编译时您不知道对象的类型,那么您就有问题了。Java有一个名为Cloneable
的接口。实际上,如果我们想使对象可克隆
,就应该实现这个接口<代码>对象。克隆
受保护,因此我们必须使用公共方法覆盖它,以使其可访问。clone()
方法也进行深度复制,这一假设风险太大。您必须控制所有类中的代码。
将基于可用的属性getter和setter克隆bean,即使bean类本身没有实现CloneablecloneBean
将在所有属性名称相同的情况下将属性值从源bean复制到目标beancopyProperties
中导入org.apache.commons.lang.SerializationUtils代码>有一种方法:
SerializationUtils.clone(Object);
例如:
this.myObjectCloned = SerializationUtils.clone(this.object);
我使用Google的JSON库对其进行序列化,然后创建序列化对象的新实例。它执行深度复制,但有一些限制:
- 不能有任何递归引用
- 它不会复制不同类型的数组
- 数组和列表应该被类型化,否则它将找不到要实例化的类
- 您可能需要在自己声明的类中封装字符串
我还使用这个类来保存用户首选项、窗口等,以便在运行时重新加载。这是非常容易使用和有效的
import com.google.gson.*;
public class SerialUtils {
//___________________________________________________________________________________
public static String serializeObject(Object o) {
Gson gson = new Gson();
String serializedObject = gson.toJson(o);
return serializedObject;
}
//___________________________________________________________________________________
public static Object unserializeObject(String s, Object o){
Gson gson = new Gson();
Object object = gson.fromJson(s, o.getClass());
return object;
}
//___________________________________________________________________________________
public static Object cloneObject(Object o){
String s = serializeObject(o);
Object object = unserializeObject(s,o);
return object;
}
}
将Cloneable
和下面的代码添加到类中
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
使用这个clonedObject=(YourClass)yourClassObject.clone()代码>深度克隆是您的答案,它需要实现Cloneable
接口并重写clone()
方法
public class DummyBean implements Cloneable {
private String dummy;
public void setDummy(String dummy) {
this.dummy = dummy;
}
public String getDummy() {
return dummy;
}
@Override
public Object clone() throws CloneNotSupportedException {
DummyBean cloned = (DummyBean)super.clone();
cloned.setDummy(cloned.getDummy());
// the above is applicable in case of primitive member types like String
// however, in case of non primitive types
// cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
return cloned;
}
}
你会这样称呼它
DummyBean dumtowo=dum.clone()代码>为什么使用反射API没有答案
private static Object cloneObject(Object obj){
try{
Object clone = obj.getClass().newInstance();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
field.set(clone, field.get(obj));
}
return clone;
}catch(Exception e){
return null;
}
}
是你
class DB {
private String dummy;
public DB(DB one) {
this.dummy = one.dummy;
}
}
public class DummyBean implements Cloneable {
private String dummy;
public void setDummy(String dummy) {
this.dummy = dummy;
}
public String getDummy() {
return dummy;
}
@Override
public Object clone() throws CloneNotSupportedException {
DummyBean cloned = (DummyBean)super.clone();
cloned.setDummy(cloned.getDummy());
// the above is applicable in case of primitive member types like String
// however, in case of non primitive types
// cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
return cloned;
}
}
private static Object cloneObject(Object obj){
try{
Object clone = obj.getClass().newInstance();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
field.set(clone, field.get(obj));
}
return clone;
}catch(Exception e){
return null;
}
}
private static Object cloneObject(Object obj){
try{
Object clone = obj.getClass().newInstance();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){
continue;
}
if(field.getType().isPrimitive() || field.getType().equals(String.class)
|| field.getType().getSuperclass().equals(Number.class)
|| field.getType().equals(Boolean.class)){
field.set(clone, field.get(obj));
}else{
Object childObj = field.get(obj);
if(childObj == obj){
field.set(clone, clone);
}else{
field.set(clone, cloneObject(field.get(obj)));
}
}
}
return clone;
}catch(Exception e){
return null;
}
}
private Object copyObject(Object objSource) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(objSource);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
try {
objDest = new ObjectInputStream(bais).readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return objDest;
}
class UserAccount{
public int id;
public String name;
}
Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);
class UserAccount{
public int id;
public String name;
//empty constructor
public UserAccount(){}
//parameterize constructor
public UserAccount(int id, String name) {
this.id = id;
this.name = name;
}
//copy constructor
public UserAccount(UserAccount in){
this(in.id,in.name);
}
}
import net.zerobuilder.BeanBuilder
@BeanBuilder
public class DummyBean {
// bean stuff
}
DummyBean bean = new DummyBean();
// Call some setters ...
// Now make a copy
DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();
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();
class DummyBean {
private String dummyStr;
private int dummyInt;
public DummyBean(String dummyStr, int dummyInt) {
this.dummyStr = dummyStr;
this.dummyInt = dummyInt;
}
public DummyBean copy() {
return new DummyBean(dummyStr, dummyInt);
}
//... Getters & Setters
}
DummyBean bean1 = new DummyBean("peet", 2);
DummyBean bean2 = bean1.copy(); // <-- Create copy of bean1
System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());
//Change bean1
bean1.setDummyStr("koos");
bean1.setDummyInt(88);
System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());
bean1: peet 2
bean2: peet 2
bean1: koos 88
bean2: peet 2
public static <T>T copyObject(Object object){
Gson gson = new Gson();
JsonObject jsonObject = gson.toJsonTree(object).getAsJsonObject();
return gson.fromJson(jsonObject,(Type) object.getClass());
}
Person copyPerson = copyObject(person);
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()
<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);