java对象浅拷贝与深拷贝区别

时间:2021-01-20 19:46:56

Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象返回的是一个新对象,而不是一个引用。二是拷贝对象与用 new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。

浅拷贝默认是不拷贝对象和数组的,只拷贝基本类型。

深拷贝:对象,对象内部的引用均复制

一个简单的例子区别浅拷贝与深拷贝

package com.pattern.clone;

import java.util.ArrayList;

public class CloneTest implements Cloneable {
    private int a;
    private int b;
    private ArrayList<String> list=new ArrayList<String>();//不会拷贝
    public void addList(String str){
        list.add(str);
    }
    public void getListValue(){
        System.out.println(list.toString());
    }
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public int getB() {
        return b;
    }
    public void setB(int b) {
        this.b = b;
    }
    @Override
    protected CloneTest clone()  {
        // TODO Auto-generated method stub
        CloneTest test=null;
        try {
            test=(CloneTest)super.clone();//浅拷贝,内部对象和数组不会拷贝
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return test;
    }
   

}

一个浅拷贝类完成,在main方法中调用

 public static void main(String[] args) {
        CloneTest test=new CloneTest();
        test.setA(10);
        test.addList("test");
        System.out.println("test a="+test.getA());
        CloneTest test1=test.clone();//拷贝对象
        test1.setA(0);//原始类型会拷贝
        test1.addList("hh");//添加list的值,test对象中的内部list也会增加

        test1.addList("test1");
        System.out.println("test1 a="+test1.getA());
        System.out.println("test a="+test.getA());
        test.getListValue();
        test1.getListValue();
    }

 

看一下程序的运行结果

test a=10
test1 a=0
test a=10
[test, hh, test1]
[test, hh, test1]

结论:浅拷贝时原始类型会拷贝,内部对象和数组不会拷贝,还是指向原生对象的内部元素地址

深拷贝的实现

 @Override
    protected CloneTest clone()  {
        // TODO Auto-generated method stub
        CloneTest test=null;
        try {
            test=(CloneTest)super.clone();
            test.list=(ArrayList<String>)list.clone();//手动拷贝内部对象和数组
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return test;
    }

 

同样执行main方法

   public static void main(String[] args) {
        CloneTest test=new CloneTest();
        test.setA(10);
        test.addList("test");
        System.out.println("test a="+test.getA());
        CloneTest test1=test.clone();
        test1.setA(0);
        test1.addList("hh");
        test1.addList("test1");
        System.out.println("test1 a="+test1.getA());
        System.out.println("test a="+test.getA());
        test.getListValue();
        test1.getListValue();
    }

输出结果;

test a=10
test1 a=0
test a=10
[test]
[test, hh, test1]

test1内部对象改变,不会引起原生内部对象的改变,两者没有任何关系