考虑下面的代码:
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呢?
这也有用。假设模型
class UserAccount{
public int id;
public String name;
}
第一次添加
编译'com.google.code.gson:gson:2.8.1'到你的应用>gradle & sync。然后
Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);
您可以通过在访问修饰符后使用瞬态关键字来排除使用字段。
注意:这是不好的做法。也不建议使用克隆或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);
}
}
90000次迭代的测试数据:
Line UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class);耗时808毫秒
Line UserAccount clone = new UserAccount(aO);耗时小于1毫秒
结论:如果你的老板很疯狂,而你喜欢速度,那就用gson吧。如果您喜欢质量,请使用第二个复制构造函数。
你也可以在Android Studio中使用复制构造函数代码生成器插件。
我使用谷歌的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;
}
}
为什么使用反射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;
}
}
这真的很简单。
EDIT:通过递归包含子对象
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;
}
}
如果可以向源文件添加注释,则可以使用注释处理器或代码生成器。
import net.zerobuilder.BeanBuilder
@BeanBuilder
public class DummyBean {
// bean stuff
}
将生成一个类DummyBeanBuilders,它有一个静态方法dummyBeanUpdater来创建浅拷贝,与手动创建的方法相同。
DummyBean bean = new DummyBean();
// Call some setters ...
// Now make a copy
DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();