java深拷贝和浅拷贝

概念

引用拷贝:只是拷贝源对象的地址,并不生成一个新的对象
浅拷贝:创建一个新对象,新对象和源对象不等,但是新对象的属性和源对象相同。
深拷贝:拷贝源对象的所有值,而不是地址

引用拷贝

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
}

测试:

public class test {
    public static void main(String[] args) {
        User user = new User(1,"jarvis");
        User user2 = user;  
        System.out.println(user.getName());
        System.out.println(user.getName());
        user.setName("sojrs");
        System.out.println(user.getName());
        System.out.println(user.getName());
    }
}
======
jarvis
jarvis
sojrs
sojrs

浅拷贝

在这里插入图片描述

  1. 如果属性是基本类型(int,double,long,boolean等),拷贝的就是基本类型的值
  2. 如果属性是引用类型,拷贝的就是内存地址(即复制引用但不复制引用的对象) ,因此如果其中一个对象的属性,就会影响到另一个对象。
    Book类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
    private int id;
    private String name;
}

User 类实现Cloneable接口

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Cloneable{
    private int id;
    private String name;
    private Book book;

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

测试

public class test {
    public static void main(String[] args) {
        User user = new User(1,"jarvis",new Book(1,"三国"));
        User user2 = null;
        try {
            user2 = user.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println(user==user2);  //false  说明克隆对象和源对象是不同的对象
        System.out.println(user.getName()==user2.getName());  //true  两个对象的name都是一样的,都指向常量池中的同一个字符串
        System.out.println(user.getBook()==user2.getBook());  //true
        user.getBook().setName("三国演义");
        System.out.println(user.getBook().getName());   //三国演义
        System.out.println(user2.getBook().getName());  //三国演义   user.book的属性改变了,影响到了user2
    }
}

Cloneable实现深拷贝

在对引用数据类型进行拷贝的时候,创建新的对象,并且复制其内的成员变量。
在这里插入图片描述
如果使用重写clone()方法实现深拷贝,那么要将类中所有自定义引用变量的类也去实现Cloneable接口实现clone()方法

Book类实现Cloneable

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book implements Cloneable{
    private int id;
    private String name;

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

User类通过Cloneable实现深拷贝

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Cloneable{
    private int id;
    private String name;
    private Book book;

    @Override
    public User clone() throws CloneNotSupportedException {
        User user2 = (User)super.clone();  //对user进行浅拷贝,获得user2
        user2.name = new String(this.name);  //将user2的name指向一个新的字符串
        user2.book = this.getBook().clone();  //将user2的book执行一个新的book
        return user2;
    }
}

测试

public class test {
    public static void main(String[] args) {
        User user = new User(1,"jarvis",new Book(1,"三国"));
        User user2 = null;
        try {
            user2 = user.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println(user==user2);  //false
        System.out.println(user.getName()==user2.getName());  //false
        System.out.println(user.getBook()==user2.getBook());  //false
    }
}

Cloneable实现深拷贝的缺点:如果引用数量或者层数太多了,会很麻烦

序列化实现深拷贝

对象序列化的时候会写到一个byte[] (或json等其他媒介)中,反序列化的时候从byte[]中读取,然后会重新创建所有的对象。
Book类实现Serializable

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book implements Serializable {
    private int id;
    private String name;
}

User类实现Serializable

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private int id;
    private String name;
    private Book book;

    protected User deepClone() throws IOException, ClassNotFoundException {
        User user2 = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        //对象的序列化输出
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(this);
        objectOutputStream.close();
        //
        ByteArrayInputStream inputStream = new ByteArrayInputStream((outputStream.toByteArray()));
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        //生成新对象
        user2 = (User)objectInputStream.readObject();
        objectInputStream.close();
        outputStream.close();
        return user2;
    }
}

测试

public class test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User user = new User(1,"jarvis",new Book(1,"三国"));
        User user2 = user.deepClone();

        System.out.println(user==user2);  //false
        System.out.println(user.getName()==user2.getName());  //false
        System.out.println(user.getBook()==user2.getBook());  //false
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值