java关于深拷贝和浅拷贝的理解

文章介绍了Java中的拷贝概念,包括浅拷贝和深拷贝。浅拷贝对于基本数据类型是值传递,而对于引用数据类型则是地址传递,意味着两个对象指向同一内存地址。深拷贝则会创建对象的新副本,存储在堆内存的新区域,修改新对象不会影响原始对象。文章提供了示例代码来演示这两种拷贝方式的效果,并指出选择拷贝类型应基于对象属性和具体需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

二、概要
1.浅拷贝
对于基本数据类型就是直接进行值传递,在内存的另一个空间内存放,修改这个值不会影响到拷贝源的值,对于引用数据类型就是进行的是地址传递,并没有对该对象重新开辟一个内存空间进行存放,所以对于引用数据类型的浅拷贝就相当于两个引用指向了同一个内存地址。

例子如下:

public class Demo{
	public static void main(String[] args){
		Student s1=new Student ("小王",22);
		try{
			Student s2=(Student)s1.clone();
		}catch(CloneNotSupportedException e) {
            e.printStackTrace();
            }
		System.out.println(s1.getName().equals(s2.getName());
		s2.setName("小李");
		System.out.println(s1.getName().equals(s2.getName());
	}
}


class Student implements Cloneable{
	private String name;
	private int age;
	public Student(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。
说明浅拷贝不会拷贝引用类型指向的对象,只会拷贝引用,指向的仍是同一个地址,所以这两个对象的引用对象是同一个对象,修改就会发生改变,浅拷贝也就是一个封装性的赋值操作。

2.深拷贝
深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
深拷贝有两种实现方式:序列化对象方式和属性二次调用clone方法。

例子如下:

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {

        CloneTest source = new CloneTest(20,new CloneTest());
        // 拷贝
        CloneTest copy = (CloneTest)source.clone();

        System.out.println("修改前:");
        System.out.println(source);
        System.out.println(copy);

        // 修改属性
        copy.setNum(23);
        copy.getCloneTest().setNum(33);

        System.out.println("修改后:");
        System.out.println(source);
        System.out.println(copy);

    }

}

@Data
@AllArgsConstructor
@NoArgsConstructor
class CloneTest implements Cloneable{

    int num;
    CloneTest cloneTest;

    @Override
    public Object clone() throws CloneNotSupportedException {
        CloneTest clone = (CloneTest)super.clone();
        
        if (null!=cloneTest){
            // 对属性进行二次clone
            clone.cloneTest =(CloneTest) cloneTest.clone();
        }
        return clone;
    }
}
---------------输出---------------------
修改前:
CloneTest(num=20, cloneTest=CloneTest(num=0, cloneTest=null))
CloneTest(num=20, cloneTest=CloneTest(num=0, cloneTest=null))
修改后:
CloneTest(num=20, cloneTest=CloneTest(num=0, cloneTest=null))
CloneTest(num=23, cloneTest=CloneTest(num=33, cloneTest=null))

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

总结:
1.如果对象的属性全是基本类型的,那么可以使用浅拷贝。
2.如果对象有引用属性,那就要基于具体的需求来选择浅拷贝还是深拷贝。
3.如果对象引用任何时候都不会被改变,那么没必要使用深拷贝,只需要使用浅拷贝就行了。
如果对象引用经常改变,那么就要使用深拷,一切都取决于具体需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜空下的星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值