深拷贝、浅拷贝

把java对象的引用复制给另外一个对象,方法有三个:1.直接赋值、2.浅拷贝、3.深拷贝

1.直接赋值
实际上,直接赋值,是对象引用的复制,即这两个引用是指向同一个内存地址。A a2=a1,引用a1和a2是指向同一个对象,当修改任何一个引用时,都是修改同一个对象。

public class Student {
    private String name;
    private int age;
    private String sex;

    public Student(String name,int age,String sex){
        this.name=name;
        this.age=age;
        this.sex=sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name){this.name=name;}

    public String getSex() {
        return sex;
    }

    public void setSex(String sex){this.sex=sex;}

    public int getAge(){
        return age;
    }

    public void setAge(int age){this.age=age;}
}

class MainTest{
    public static void main(String[] args){
        Student student=new Student("小晴 ",15,"男");
        System.out.println("姓名:"+student.getName()+"  年龄:"+student.getAge()+"   性别:"+student.getSex());
        Student student1=student;
        student1.setAge(100);
        System.out.println("姓名:"+student1.getName()+"  年龄:"+student1.getAge()+"   性别:"+student1.getSex());
    }
}

输出:

姓名:小晴   年龄:15   性别:男
姓名:小晴   年龄:100   性别:男

可见两个引用实际指向同一个对象。

2.浅拷贝

如果想要两个引用相互独立,互不影响,我们可以利用Object 的clone()方法。而浅拷贝是指,如果是对象的非静态普通成员变量(值变量),则直接复制;如果是非静态类对象(引用类型),则复制引用但不复制引用的对象。

//对象内成员都是值变量
public class Student implements Cloneable{
    private String name;
    private int age;
    private String sex;

    public Student(String name,int age,String sex){
        this.name=name;
        this.age=age;
        this.sex=sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name){this.name=name;}

    public String getSex() {
        return sex;
    }

    public void setSex(String sex){this.sex=sex;}

    public int getAge(){
        return age;
    }

    public void setAge(int age){this.age=age;}

    public Object clone(){
        try {
            return (Student)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}

class MainTest{
    public static void main(String[] args){
        Student student=new Student("小晴 ",15,"男");
        System.out.println("姓名:"+student.getName()+"  年龄:"+student.getAge()+"   性别:"+student.getSex());
        Student student1=(Student) student.clone();
        student1.setAge(100);
        System.out.println("姓名:"+student1.getName()+"  年龄:"+student1.getAge()+"   性别:"+student1.getSex());
        System.out.println("姓名:"+student.getName()+"  年龄:"+student.getAge()+"   性别:"+student.getSex());
    }
}

姓名:小晴   年龄:15   性别:男
姓名:小晴   年龄:100   性别:男
姓名:小晴   年龄:15   性别:男
//成员有个类类型引用变量
public class Student implements Cloneable{
    private String name;
    private int age;
    private String sex;

    private Mother mother;

    public Student(String name,int age,String sex){
        this.name=name;
        this.age=age;
        this.sex=sex;
        this.mother=new Mother();
    }

    public Mother getMother() {
        return mother;
    }

    public void setMother(String name){mother.setName(name);}

    public String getName() {
        return name;
    }

    public void setName(String name){this.name=name;}

    public String getSex() {
        return sex;
    }

    public void setSex(String sex){this.sex=sex;}

    public int getAge(){
        return age;
    }

    public void setAge(int age){this.age=age;}

    public Object clone(){
        try {
            return (Student)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}

class MainTest{
    public static void main(String[] args){
        Student student=new Student("小晴 ",15,"男");
        student.setMother("andy");
        System.out.println("姓名:"+student.getName()+"  年龄:"+student.getAge()+"   性别:"+student.getSex()+"   mother:"+student.getMother().toString());
        Student student1=(Student) student.clone();
        student1.setAge(100);
        student1.setMother("alice");
        System.out.println("姓名:"+student1.getName()+"  年龄:"+student1.getAge()+"   性别:"+student1.getSex()+"   mother:"+student1.getMother().toString());
        System.out.println("姓名:"+student.getName()+"  年龄:"+student.getAge()+"   性别:"+student.getSex()+"   mother:"+student.getMother().toString());
    }
}

姓名:小晴   年龄:15   性别:男   mother:andy
姓名:小晴   年龄:100   性别:男   mother:alice
姓名:小晴   年龄:15   性别:男   mother:alice

可见浅拷贝只会复制值变量,对于引用类型还是只想同一个对象。

3.深拷贝
顾名思义,深拷贝就是要拷贝一个完全独立的对象。在浅拷贝的基础上,我只需要把引用类型变量指向不同的对象即可。只需修改:

//浅拷贝
 public void setMother(String name){mother.setName(name);}
 //深拷贝
 public void setMother(String name) {
        mother=new Mother();//重新创建一个对象,即可指向不同的对象空间了。
        mother.setName(name);
    }

姓名:小晴   年龄:15   性别:男   mother:andy
姓名:小晴   年龄:100   性别:男   mother:alice
姓名:小晴   年龄:15   性别:男   mother:andy

另一种方式,对Mother对象也进行clone方法覆盖:

package com.example.demo.common;

public class Student implements Cloneable {
    private String name;
    private int age;
    private String sex;
    private Mother mother;

    public Student(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.mother = new Mother();
    }

    public Mother getMother() {
        return mother;
    }

    public void setMother(String name) {
//        mother=new Mother();
        mother.setName(name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Object clone() {
        Student student=null;
        try {
            student=(Student) super.clone();
            student.mother=(Mother)mother.clone();
            return student;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}

class MainTest {
    public static void main(String[] args) {
        Student student = new Student("小晴 ", 15, "男");
        student.setMother("andy");
        System.out.println("姓名:" + student.getName() + "  年龄:" + student.getAge() + "   性别:" + student.getSex() + "   mother:" + student.getMother().toString());
        Student student1 = (Student) student.clone();
        student1.setAge(100);
        student1.setMother("alice");
        System.out.println("姓名:" + student1.getName() + "  年龄:" + student1.getAge() + "   性别:" + student1.getSex() + "   mother:" + student1.getMother().toString());
        System.out.println("姓名:" + student.getName() + "  年龄:" + student.getAge() + "   性别:" + student.getSex() + "   mother:" + student.getMother().toString());
    }
}

class Mother implements Cloneable {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }

    public Object clone(){
        try {
            Mother mother=(Mother)super.clone();
            return mother;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}
### 深拷贝浅拷贝的概念 在 Python 中,深拷贝浅拷贝用于处理数据结构的复制操作。浅拷贝仅创建对象的新引用,而不实际复制内部的对象内容;而深拷贝则会递归地复制整个对象及其嵌套的内容。 #### 浅拷贝的特点 当执行浅拷贝时,新对象会被创建,但对于可变类型的元素(如列表或字典),其内部的子对象不会被真正复制,而是共享相同的内存位置[^2]。这意味着修改原始对象中的某些部分可能会影响副本。 #### 深拷贝的特点 相比之下,深拷贝不仅复制顶层容器本身,还会递归地复制所有的子对象到新的存储空间中[^1]。因此,在任何层次上更改原对象都不会影响它的深层副本。 ### 实现方法对比 以下是两种不同方式的具体实现: #### 使用 `copy` 模块进行浅拷贝 ```python import copy original_list = [[1, 2], [3, 4]] shallow_copied_list = copy.copy(original_list) print(shallow_copied_list is original_list) # False (不同的顶级列表实例) print(shallow_copied_list[0] is original_list[0]) # True (相同的第一层子项) ``` 上述例子展示了通过调用 `copy.copy()` 函数来完成一次浅拷贝的过程。 #### 利用 `deepcopy` 方法达成完全独立的复制品 对于更复杂的场景,则需借助于 `copy.deepcopy()` 来获得真正的分离版本: ```python import copy original_dict = {"key": [1, 2]} deep_copied_dict = copy.deepcopy(original_dict) print(deep_copied_dict["key"] is original_dict["key"]) # False (各自拥有独立数组) ``` 这里可以看出即使是在多级嵌套情况下也能保持彼此间的隔离状态。 ### 总结说明 综上所述,选择合适的策略取决于具体需求——如果只需要简单表面级别的保护即可满足应用逻辑的话那么采用轻量化的浅拷贝就足够了; 反之亦然需要考虑性能开销的同时兼顾安全性的时候就应该倾向运用耗资源更多的深度克隆技术.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值