How do I copy an object in Java?
考虑下面的代码:
1 2 3 4 5 6 7 8 9 |
所以,我想复制到
我想,当我说
创建复制构造函数:
1 2 3 4 5 6 7 | class DummyBean { private String dummy; public DummyBean(DummyBean another) { this.dummy = another.dummy; // you can access } } |
每个对象都有一个克隆方法,可以用来复制对象,但不要使用它。创建类和执行不正确的克隆方法太容易了。如果你要这么做,至少读一下Joshua Bloch在有效Java中所说的话。
Basic:Java中的对象复制。
让我们假设一个对象-
浅复制:
浅复制创建同一类的新
深度复制:
当对象与其引用的对象一起复制时,将发生深度复制。下图显示了对其执行深度复制后的
可能的问题:
最好使用防御性复制、复制构造函数(如@egaga reply)或静态工厂方法。
例如,org.apache.commons.lang.serializationutils将具有使用序列化(source)进行深度克隆的方法。如果我们需要克隆bean,那么在org.apache.commons.beanutils(源代码)中有两种实用方法。
cloneBean 将基于可用的属性getter和setter克隆bean,即使bean类本身不实现可克隆。- 对于所有属性名称相同的情况,
copyProperties 都会将属性值从源bean复制到目标bean。
在
1 |
例子:
1 | this.myObjectCloned = SerializationUtils.clone(this.object); |
如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
无论您想在哪里获得另一个对象,只需执行克隆即可。例如:
1 2 3 4 | Deletable del = new Deletable(); Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent // object, the changes made to this object will // not be reflected to other object |
为什么使用反射API没有答案?
1 2 3 4 5 6 7 8 9 10 11 12 |
这真的很简单。
编辑:通过递归包含子对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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; } } |
我使用Google的JSON库将其序列化,然后创建序列化对象的新实例。它可以进行深度复制,但有一些限制:
不能有任何递归引用
它不会复制不同类型的数组
数组和列表应该是类型化的,否则它找不到要实例化的类
您可能需要在声明自己的类中封装字符串。
我还使用这个类保存用户首选项、窗口以及运行时不需要重新加载的内容。它非常容易使用和有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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; } } |
是的,您只是在引用对象。如果对象实现了
看看这个关于复制对象的wiki文章。
请参阅:对象复制
对。你需要深度复制你的对象。
将
1 2 3 |
用这个
这里有一个很好的关于
这里:克隆(Java方法)
这也行。假设模型
1 2 3 4 |
第一次添加
1 2 | Gson gson = new Gson(); updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class); |
通过在访问修饰符后使用
注意:这是不好的做法。也不建议使用
类似的东西
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
90000次迭代的测试状态:
结论:如果你的老板疯了,你更喜欢速度,那就使用GSON。如果您喜欢质量,请使用第二个副本构造函数。
您也可以在Android Studio中使用复制构造函数代码生成器插件。
使用深度克隆实用程序:
1 | SomeObjectType copy = new Cloner().deepClone(someObject); |
这将深度复制任何Java对象,在HTTPS://GITHUBCOM/KOSTASKOGIOSOS/克隆中进行检查
要做到这一点,您必须以某种方式克隆对象。虽然Java有一个克隆机制,但是如果你不需要的话,就不要使用它。创建一个复制方法,该方法为您完成复制工作,然后执行以下操作:
1 | dumtwo = dum.copy(); |
以下是关于完成副本的不同技术的更多建议。
深度克隆是您的答案,它需要实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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, // however, in case of non primitive types // cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone()); return cloned; } } |
你可以这样称呼它
除了显式复制之外,另一种方法是使对象不可变(没有
1 2 3 4 5 6 7 |
传递要复制的对象并获取所需的对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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; } |
现在将
快乐编码!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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(); } } } |
在你的代码中:
1 2 3 | MyClass myClass = new MyClass(); // do some work with this object MyClass clonedMyClass = myClass.clone(); |
您可以使用x stream从http://x-stream.github.io/自动进行深度复制:
XStream is a simple library to serialize objects to XML and back
again.
将其添加到项目中(如果使用maven)
1 2 3 4 5 | <dependency> <groupId>com.thoughtworks.xstream</groupId> xstream</artifactId> <version>1.3.1</version> </dependency> |
然后
1 2 3 | DummyBean dum = new DummyBean(); dum.setDummy("foo"); DummyBean dumCopy = (DummyBean) XSTREAM.fromXML(XSTREAM.toXML(dum)); |
有了这个,您就有了一个副本,不需要实现任何克隆接口。
您可以尝试实现
如果可以将注释添加到源文件中,则可以使用这样的注释处理器或代码生成器。
1 2 3 4 5 6 | import net.zerobuilder.BeanBuilder @BeanBuilder public class DummyBean { // bean stuff } |
将生成一个类
1 2 3 4 | DummyBean bean = new DummyBean(); // Call some setters ... // Now make a copy DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done(); |