Java高级进阶

Java------List的深拷贝与浅拷贝

2020-08-09  本文已影响0人  Albert0211
0.jpg

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、 将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。

上一篇下一篇

猜你喜欢

热点阅读