Vee*_*era 763 java clone copy object
请考虑以下代码:
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'
Run Code Online (Sandbox Code Playgroud)
所以,我想复制dum到dumtwo并更改dum而不影响dumtwo.但上面的代码并没有这样做.当我改变某些内容时dum,也会发生同样的变化dumtwo.
我想,当我说dumtwo = dum,Java 只复制引用.那么,有没有办法创建一个新的副本dum并分配给它dumtwo?
ega*_*aga 598
创建一个复制构造函数:
class DummyBean {
private String dummy;
public DummyBean(DummyBean another) {
this.dummy = another.dummy; // you can access
}
}
Run Code Online (Sandbox Code Playgroud)
每个对象都有一个克隆方法,可用于复制对象,但不要使用它.创建类并执行不正确的克隆方法太容易了.如果您打算这样做,请至少阅读Joshua Bloch在Effective Java中对此所说的内容.
Cha*_*har 392
基本: Java中的对象复制.
让我们假设一个对象- obj1,它包含两个对象,containedObj1和containedObj2.

浅拷贝:
浅拷贝创建instance同一个类的新东西,并将所有字段复制到新实例并返回它.Object类提供了一种clone方法,并为浅复制提供支持.

深度复制:
当对象与其引用的对象一起复制时,会发生深层复制.下图显示obj1了对其进行深度复制后的情况.不仅obj1已复制,而且其中包含的对象也已被复制.我们可以Java Object Serialization用来做一个深层复制.不幸的是,这种方法也有一些问题(详细的例子).

可能的问题:
clone正确实施很棘手.
最好使用防御性复制,复制构造函数(如@egaga回复)或静态工厂方法.
clone()方法,但是你在编译时不知道对象的类型,那么你就有问题了.Java有一个名为的接口Cloneable.实际上,如果我们想要创建一个对象,我们应该实现这个接口Cloneable.Object.clone被保护的,所以我们必须重写与公共方法,以它为它进行访问.clone()所有成员对象变量的方法也进行深度复制,这对假设来说风险太大.您必须控制所有类中的代码.例如,org.apache.commons.lang.SerializationUtils将使用序列化(源)进行深度克隆的方法.如果我们需要克隆Bean,那么org.apache.commons.beanutils(Source)中有几个实用程序方法.
cloneBean 将基于可用的属性getter和setter克隆bean,即使bean类本身没有实现Cloneable.copyProperties 对于属性名称相同的所有情况,将属性值从原始bean复制到目标bean.小智 119
在包中import org.apache.commons.lang.SerializationUtils;有一个方法:
SerializationUtils.clone(Object);
Run Code Online (Sandbox Code Playgroud)
例:
this.myObjectCloned = SerializationUtils.clone(this.object);
Run Code Online (Sandbox Code Playgroud)
小智 101
请按以下步骤操作:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
无论你想要获得另一个对象,只需执行克隆即可.例如:
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
Run Code Online (Sandbox Code Playgroud)
Wil*_*ner 37
为什么没有使用Reflection 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;
}
}
Run Code Online (Sandbox Code Playgroud)
这很简单.
编辑:通过递归包含子对象
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;
}
}
Run Code Online (Sandbox Code Playgroud)
Pet*_*ter 28
我使用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;
}
}
Run Code Online (Sandbox Code Playgroud)
Tej*_*idu 12
Cloneable在您的班级中添加和下面的代码
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
Run Code Online (Sandbox Code Playgroud)
用这个 clonedObject = (YourClass) yourClassObject.clone();
Qam*_*mar 11
这也有效.假设模型
class UserAccount{
public int id;
public String name;
}
Run Code Online (Sandbox Code Playgroud)
首先添加
compile 'com.google.code.gson:gson:2.8.1'到您的应用> gradle&sync.然后
Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);
Run Code Online (Sandbox Code Playgroud)
您可以transient在访问修饰符后使用关键字排除使用字段.
注意:这是不好的做法.也不建议使用Cloneable或JavaSerialization它的速度慢而且破碎.编写复制构造函数以获得最佳性能参考.
就像是
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);
}
}
Run Code Online (Sandbox Code Playgroud)
测试90000次迭代的统计数据:
行UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class);需要808ms
线路UserAccount clone = new UserAccount(aO);不到1 毫秒
结论:如果你的老板很疯狂并且你更喜欢速度,请使用gson.如果您喜欢质量,请使用第二个复制构造函数
您还可以在Android Studio中使用复制构造函数代码生成器插件.
使用深度克隆实用程序:
SomeObjectType copy = new Cloner().deepClone(someObject);
Run Code Online (Sandbox Code Playgroud)
这将深度复制任何java对象,请访问https://github.com/kostaskougios/cloning
深度克隆是您的答案,需要实现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,
// however, in case of non primitive types
// cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
return cloned;
}
}
Run Code Online (Sandbox Code Playgroud)
你会这样称呼它
DummyBean dumtwo = dum.clone();
传递你想要复制的对象并获取你想要的对象:
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;
}
Run Code Online (Sandbox Code Playgroud)
现在解析objDest到所需的对象。
快乐编码!
替代egaga 的构造函数复制方法。您可能已经有一个 POJO,因此只需添加另一个copy()返回已初始化对象副本的方法。
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
}
Run Code Online (Sandbox Code Playgroud)
如果您已经有一个DummyBean并想要一个副本:
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());
Run Code Online (Sandbox Code Playgroud)
输出:
Run Code Online (Sandbox Code Playgroud)bean1: peet 2 bean2: peet 2 bean1: koos 88 bean2: peet 2
但两者都很好,最终取决于你......
要做到这一点,你必须以某种方式克隆对象.尽管Java具有克隆机制,但如果您不需要,请不要使用它.创建一个复制方法,使复制工作为您,然后执行:
dumtwo = dum.copy();
Run Code Online (Sandbox Code Playgroud)
以下是有关完成复制的不同技术的更多建议.
除了显式复制之外,另一种方法是使对象不可变(无set或其他mutator方法).这样就不会出现问题.对于较大的物体,不变性变得更加困难,但另一方面是它将你推向分裂成连贯的小物体和复合物的方向.
使用gson用于复制的对象。
public static <T>T copyObject(Object object){
Gson gson = new Gson();
JsonObject jsonObject = gson.toJsonTree(object).getAsJsonObject();
return gson.fromJson(jsonObject,(Type) object.getClass());
}
Run Code Online (Sandbox Code Playgroud)
假设我有一个对象person。所以
Person copyPerson = copyObject(person);
Run Code Online (Sandbox Code Playgroud)
注意:性能要慢得多。