zoukankan      html  css  js  c++  java
  • 深拷贝和浅拷贝

    Object 类的clone() 方法 : 

      clone() 指创建并返回此对象的一个副本。(通过clone()方法返回一个新的对象,且新的对象的属性值从原对象拷贝)。

      clone() 是 Object 类的方法,所以每一个类都会从Object类继承此方法。

    如何实现clone :  实现 Cloneable 接口 , 重写clone() 方法

      使用某个类的clone()方法,必须要实现 Cloneable 接口。否则会抛 java.lang.CloneNotSupportedException)因为Object 类本身不实现Cloneable接口,所以使用Object对象调用clone()方法时会抛出运行时异常 java.lang.CloneNotSupportedException。

      Object 类的 clone()方法是 protected修饰的,所以要重写clone()方法,并且将 protected 改为 public修饰。

    @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }

     从内存分析深拷贝和浅拷贝的区别,以Car和Wheel为例

    package com.nemo.clone;
    // 车轮 类
    public class Wheel {
        private String name;
    
        public Wheel(String name) {
            this.name = name;
        }
        
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    package com.nemo.clone;
    
    public class Car implements Cloneable {
        private int id;
        private String type;
        //汽车 和 车轮 是组合关系
        private Wheel wheel;
    
        public Car (Wheel wheel) {
            this.wheel = wheel;
        }
        
        // 重写 clone() 方法
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public String getType() {
            return type;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getId() {
            return id;
        }
    
        public Wheel getWheel() {
            return wheel;
        }
    
        public void setWheel(Wheel wheel) {
            this.wheel = wheel;
        }
    }
    package com.nemo.clone;
    
    public class Test {
        public static void main(String[] args) throws CloneNotSupportedException {
            Wheel wheel = new Wheel("XXX"); // 创建一个车轮
            Car car = new Car(wheel);
            car.setId(123);
            car.setType("Audi");
            car.getWheel().setName("AAA"); //将车轮的name改为 AAA
            
            Car cloneCar = (Car)car.clone(); // clone 一个Car 
            cloneCar.setId(456); 
            cloneCar.setType("Benz");
            
            cloneCar.getWheel().setName("BBB"); // 通过cloneCar 将车轮的name 改为 BBB
            
            System.out.println(car);
            System.out.println(car.getId() + "  " + car.getType());
            System.out.println(car.getWheel());
            System.out.println(car.getWheel().getName());
            System.out.println("------------------------------------------");
            System.out.println(cloneCar);
            System.out.println(cloneCar.getId() + "  " + cloneCar.getType());
            System.out.println(cloneCar.getWheel());
            System.out.println(cloneCar.getWheel().getName());
        }
    }
    com.nemo.clone.Car@1fb8ee3
    123  Audi
    com.nemo.clone.Wheel@61de33
    BBB
    ------------------------------------------
    com.nemo.clone.Car@14318bb
    456  Benz
    com.nemo.clone.Wheel@61de33
    BBB


    从输出可以看出 car和拷贝出来的cloneCar的哈希码不同,car 的 id,type 和 cloneCar的id,type 也不同。(红色标识)
    car的Wheel对象和cloneCar的Wheel对象哈希码相同,说明他们共享一个Wheel引用。所以当car更改了Wheel的name为"AAA"后cloneCar也更改Wheel的name为"BBB"最后car和cloneCar的name都输出BBB。(car和cloneCar共享一个引用 cloneCar后执行cloneCar.getWheel.setName("BBB") );
    
    

    (哈希码 : 指的是JAVA通过某算法将对象的地址生成16进制的字符串。用于唯一标识某对象)

     

    以上为浅拷贝。

    下面是深拷贝的例子

    package com.nemo.clone;
    // 车轮 类
    public class Wheel implements Cloneable{
        private String name;
    
        public Wheel(String name) {
            this.name = name;
        }
        
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
        
        // 重写 clone() 方法
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    package com.nemo.clone;
    
    public class Car implements Cloneable {
        private int id;
        private String type;
        //汽车 和 车轮 是组合关系
        private Wheel wheel;
    
        public Car (Wheel wheel) {
            this.wheel = wheel;
        }
        
        // 重写 clone() 方法
        @Override
        public Object clone() throws CloneNotSupportedException {
            Car object =  (Car)super.clone();
            object.wheel = (Wheel)wheel.clone();
            return object;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public String getType() {
            return type;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getId() {
            return id;
        }
    
        public Wheel getWheel() {
            return wheel;
        }
    
        public void setWheel(Wheel wheel) {
            this.wheel = wheel;
        }
    }
    package com.nemo.clone;
    
    public class Test {
        public static void main(String[] args) throws CloneNotSupportedException {
            Wheel wheel = new Wheel("XXX"); // 创建一个车轮
            Car car = new Car(wheel);
            car.setId(123);
            car.setType("Audi");
            car.getWheel().setName("AAA"); //将车轮的name改为 AAA
            
            Car cloneCar = (Car)car.clone(); // clone 一个Car 
            cloneCar.setId(456); 
            cloneCar.setType("Benz");
            
            cloneCar.getWheel().setName("BBB"); // 通过cloneCar 将车轮的name 改为 BBB
            
            System.out.println(car);
            System.out.println(car.getId() + "  " + car.getType());
            System.out.println(car.getWheel());
            System.out.println(car.getWheel().getName());
            System.out.println("------------------------------------------");
            System.out.println(cloneCar);
            System.out.println(cloneCar.getId() + "  " + cloneCar.getType());
            System.out.println(cloneCar.getWheel());
            System.out.println(cloneCar.getWheel().getName());
        }
    }
    输出结果 : 
    com.nemo.clone.Car@1fb8ee3
    123 Audi com.nemo.clone.Wheel@61de33 AAA ------------------------------------------ com.nemo.clone.Car@14318bb 456 Benz com.nemo.clone.Wheel@ca0b6 BBB

    (红色标识的是与上一个例子不同的地方)
    从输出结果可以看出 car和cloneCar的Wheel对象哈希码不同,说明car和cloneCar不再共享同一wheel对象。

     

     (

      采用clone()方法这种方式拷贝对象,其实并不好用。每一个类都需要实现cloneable接口,重写clone方法。当类的等级结构很深的时候会很乱。

      另一种拷贝对象的方法是 采用序列化的方式。

       // JAVA创建对象的几种方式

    )

  • 相关阅读:
    PAT1064(上)分析部分
    网络支付极其简单的体会
    L3,please send me a card
    PAT1008
    里氏转换
    数组遍历问题
    注册登录界面(简陋版)
    表单事件,onblur,onfocus,焦点
    复制所有链接,全选,反选
    剪切板
  • 原文地址:https://www.cnblogs.com/shouwangzhe-/p/3630962.html
Copyright © 2011-2022 走看看