美文网首页
深拷贝、浅拷贝

深拷贝、浅拷贝

作者: 杨0612 | 来源:发表于2021-10-22 17:24 被阅读0次
    创建对象普遍有两种方式:构建和拷贝。

    构建是用new的方式,适合构建初始化状态对象的情况;
    拷贝是用clone的方式,适合对象数据完全复制的情况,这里我们主要讨论clone。
    以下代码定义Car类,包含price和brand两个基本数据类型的属性。先是构建car1,然后clone得到car2,由于Car类的属性都是基本数据类型,所以不需要考虑深、浅拷贝问题。

    //汽车
    class Car(var price: Double, val brand: String) : Cloneable {
        public override fun clone(): Car {
            return super.clone() as Car
        }
    }
    
          //调用
            val car1 = Car(100000.0, "tmw")
            val car2 = car1.clone()
            val isSame = car1 == car2
            println("是否同一个对象$isSame")
    
           //日志
           是否同一个对象:false
    

    如果Car中包含引用属性,那就需要深、浅拷贝的问题。
    以下代码跟上述类似,只不过增加了一个轮胎属性Tyre。从打印日志可以看到,虽然car1、car2不是同一个对象,但是他们的轮胎属性是同一个,如果修改了car1的轮胎属性,那么car2的也会被修改,这就是浅拷贝问题。

    //轮胎
    class Tyre(var size: Double, val brand: String)
    
    //汽车
    class Car(var price: Double, val brand: String, var tyre: Tyre) : Cloneable {
        public override fun clone(): Car {
            return super.clone() as Car
        }
    }
    
            //调用
            val car1 = Car(100000.0, "tmw",Tyre(10.0,"普利司通"))
            val car2 = car1.clone()
            val isSame = car1 == car2
            println("是否同一个对象:$isSame")
    
            val isSameTyre = car1.tyre == car2.tyre
            println("是否同一个轮胎:$isSameTyre")
    
             //日志
             是否同一个对象:false
             是否同一个轮胎:true
    

    如果不希望car1、car2的轮胎属性是同一个,那么就需要用深拷贝。其实也很简单,只要Tyre实现Cloneable接口,重写clone()方法,Car类对轮胎属性进行clone即可,具体代码如下:

    //轮胎
    class Tyre(var size: Double, val brand: String):Cloneable{
        public override fun clone(): Tyre {
            return super.clone() as Tyre
        }
    }
    
    //汽车
    class Car(var price: Double, val brand: String, var tyre: Tyre) : Cloneable {
    
        public override fun clone(): Car {
            val clone = super.clone() as Car
            clone.tyre = tyre.clone()
            return clone
        }
    }
    
    集合的深拷贝

    当集合的元素为引用类型,需要遍历调用元素的clone方法;

            //原始数据
            val cars = mutableListOf<Car>()
            cars.add(Car(100000.0, "tmw", Tyre(10.0, "普利司通")))
            cars.add(Car(120000.0, "tmw", Tyre(10.0, "普利司通")))
            cars.add(Car(130000.0, "tmw", Tyre(10.0, "普利司通")))
    
            //clone数据
            val cloneCars = mutableListOf<Car>()
            cars.forEach {
                cloneCars.add(it.clone())
            }
    

    当集合元素为基本数据类型,可以直接赋值:

            //原始数据
            val data = mutableListOf<Long>()
            data.add(1)
            data.add(2)
            data.add(3)
    
            //clone数据
            val cloneData = mutableListOf(data)//注意这里直接用data赋值,如果data元素是引用类型,那么这里的拷贝是浅拷贝
    
    总结

    1.深、浅拷贝区别在于:内部的引用属性clone前后是否是同一个;
    2.mutableListOf(data),内部是浅拷贝,不适合data元素是引用类型的情况;
    3.对象中有枚举属性,不需要做特殊处理,底层clone会处理。

    以上分析有不对的地方,请指出,互相学习,谢谢哦!

    相关文章

      网友评论

          本文标题:深拷贝、浅拷贝

          本文链接:https://www.haomeiwen.com/subject/alocaltx.html