欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

深拷贝和浅拷贝

程序员文章站 2022-05-13 23:50:17
...

基础知识

1、基本数据类型:保存的是值本身;
2、引用类型:保存的是指向堆中数据的地址;

拷贝

对象拷贝指的就是将一个对象的所有属性(成员属性)拷贝到一个有着相同类型的对象中去
Java中的数据类型分为基本数据类习和引用数据类型,对于这两种数据类型,在进行赋值、用作方法参数、返回值的时候,会有值传递和地址传递的差别。

步入正题

一、浅拷贝(Shallow Copy)

浅拷贝对于基本数据类型就是直接进行值传递,在内存的另一个空间内存放,修改这个值不会影响到拷贝源的值
浅拷贝对于引用数据类型就是进行的是地址传递,并没有对该对象重新开辟一个内存空间进行存放,所以对于引用数据类型的浅拷贝就相当于两个引用指向了同一个内存地址,
那么就显而易见了修改拷贝后的值就会影响到拷贝源的值,有C/C++基础的奋斗者应该很好理解

上代码

public class Main{
	public static void main(String[] args){
		Person p1=new Person("张三",24);
		try{
			Person p2=(Person)p1.clone();
		}catch(CloneNotSupportedException e) {
            e.printStackTrace();
            }
		System.out.println(p1.getName().equals(p2.getName());
		p2.setName("李四");
		System.out.println(p1.getName().equals(p2.getName());
	}
}


class Person implements Cloneable{
	private String name;
	private int age;
	public person(String name,int age){
		this.name=name;
		this.age=age;
	}
	public String getName(){
		return this.name;
	}
	public void setName(String name){
		this.name=name;
	}

	@override
	public Object clone()throws CloneNotSupportedException{
		return super.clone();//浅拷贝
	}
}

结果是:

true
true

这里证明浅拷贝不会拷贝引用类型指向的对象,只会拷贝引用,所以这两个对象的引用对象是同一个对象,修改就会发生改变,浅拷贝也就是一个封装性的赋值操作。

二、深拷贝(Deep Copy)
深拷贝又成为深度拷贝,所拷贝的对象的内部的引用类型也需要实现clone()这个方法,

上代码

public class Main {
    public static void main(String[] args){
        Person p1=new Person(new Son());
        try {
            Person p2=(Person)p1.clone();
            p2.setSonNum(44);
            System.out.println(p1.getSonNum()+"===>"+p2.getSonNum());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

class Person implements Cloneable{
    private Son son;

    public Person(Son son) {
        this.son=son;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person per=null;
        try {
            per=(Person)super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        per.son=(Son)son.clone();
        return  per;
    }

  
    public void setSonNum(int num){
        this.son.setNum(num);
    }
    public int getSonNum(){
        return this.son.getNum();
    }
}



class Son implements Cloneable{
    private int num=10;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

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

结果为:

10===>44

这里就证明了深拷贝就会连引用类型也拷贝一份。

总结:

Object中的clone()执行的时候使用RTTI机制(run-time type identification);
动态找到目前正在调用clone()方法的那个引用,根据它的大小申请内存空间,然后进行字段的赋值,将该对象的内存空间完全复制到新的空间去。