Java的浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。
浅拷贝(Shallow Copy)
1、对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
2、对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
深拷贝 (Deep Copy)
相对于浅拷贝而言,对于引用类型的修改,并不会影响到对应的copy对象的值。
最近项目中用到ArrayList,对于ArrayList的怎么实现拷贝,尤其是里边存放复杂对象,该怎么处理?
怎么判断两个集合相等,存放的是稍微复杂的对象,非字符串String? 方法很多,比如:
/**
* 判断两个集合是否相等
*/
public static boolean isCagoryEqual(List<Category> src, List<Category> dest) {
if (src.size() != dest.size()) {
return false;
}
for (Category fo : src) {
if (!dest.contains(fo)) {
return false;
}
}
return true;
}
这样,好像还不够,如何判断里边的对象是否相等呢?
请允许我来一段kotlin代码,为什么重写equals,hashCode?
class Category() : Serializable {
var id: String = ""
var name: String = ""
var priority: Int = 0
var restaurantId: String = ""
var isChecked: MutableList<Int> = ArrayList<Int>()
private val serialVersionUID = 1L
override fun equals(other: Any?): Boolean {
if (other is FoodCategory) {
val foodCategory = other as FoodCategory
return this.id.equals(foodCategory.id) && this.name.equals(foodCategory.name)
}
return super.equals(other)
}
override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + name.hashCode()
return result
}
}
需求是两个list不相等,则要使用原来的数据,显示界面,所以要深拷贝原来的list数据。直接贴代码:
public static <E> List<E> copy(List<E> src) {
try {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(src);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
@SuppressWarnings("unchecked")
List<E> dest = (List<E>) in.readObject();
return dest;
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<E>();
}
}
如果新旧list数据不一样,撤销新编辑的数据,怎么处理呢?
newList.clear()
for (i in 0 until oldList.size) {
val category = Category()
category.name = oldList[i].name
category.id = oldList[i].id
category.restaurantId = oldList[i].restaurantId
...
newList.add(category)
}
总结:
1、Java对对象和基本的数据类型的处理是不一样的。在Java中用对象的作为入口参数的传递则缺省为”引用传递”,也就是说仅仅传递了对象的一个”引用”。当函数体内部对输入变量改变时,实质上就是在对这个对象的直接操作。 除了在函数传值的时候是”引用传递”,在任何用”=”向对象变量赋值的时候都是”引用传递”。
2、 将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。
网友评论