Java中的浅拷贝和深拷贝是什么

发布时间:2023年12月22日

Java中常见的创建对象方式有5种。其中包括了克隆和通过对象序列化(Serialization)两种方式。

这两者的差别就有一个,克隆是浅拷贝,对象序列化是深拷贝。

那么深拷贝和浅拷贝到底是什么呢:

  1. 浅拷贝(Shallow Copy):浅拷贝会创建一个新对象,该对象的字段将是原始对象字段的副本。如果字段本身是引用类型,则引用字段仍然会共享原始对象和副本对象之间的相同引用。浅拷贝只是复制对象的引用,而不是创建对象的副本。?

  2. 深拷贝(Deep Copy):深拷贝将创建一个新对象,并且复制对象的所有字段,包括引用字段。新对象和原始对象之间的引用是完全独立的。深拷贝会递归复制对象的所有引用类型字段及其引用的对象。

浅拷贝时,对于原始对象中的引用类型字段,克隆对象会共享相同的引用。也就是说,如果你修改了user1中引用类型字段的值,这个修改也会反映在user2中。这可能会导致一些数据不一致的问题。

class User implements Cloneable {
 ? ?private String username;
?
 ? ?public User(String username) {
 ? ? ? ?this.username = username;
 ?  }
?    
    //get、set

?
 ? ?@Override
 ? ?protected Object clone() throws CloneNotSupportedException {
 ? ? ? ?return super.clone();
 ?  }
}
?
public class Main {
 ? ?public static void main(String[] args) throws CloneNotSupportedException {
 ? ? ? ?User user1 = new User("Alice");
?
 ? ? ? ?// 使用浅拷贝克隆对象
 ? ? ? ?User user2 = (User) user1.clone();
?
 ? ? ? ?System.out.println(user1.getUsername()); ?// 输出: Alice
 ? ? ? ?System.out.println(user2.getUsername()); ?// 输出: Alice
?
 ? ? ? ?user1.setUsername("Bob");
?
 ? ? ? ?System.out.println(user1.getUsername()); ?// 输出: Bob
 ? ? ? ?System.out.println(user2.getUsername()); ?// 输出: Bob (引用字段被共享)
 ?  }
}

在上面的代码中我们可以看到,当user1username属性值被改了之后,user2username属性值也发生了改变,而这是因为user1user2共享了相同的引用。

另外对于基本数据类型(如intbooleandouble等),在浅拷贝中是不存在共享引用的问题的。因为基本数据类型直接存储的是值,而不是引用。

当使用clone()进行浅拷贝时,基本数据类型的值会被复制到新的对象中,而新对象和原始对象之间是相互独立的。因此,如果你修改原始对象中的基本数据类型的值,不会影响到克隆对象。

还是来段代码示例来说明这个问题:

class Data implements Cloneable {
 ? ?private int value;
?
 ? ?public Data(int value) {
 ? ? ? ?this.value = value;
 ?  }
?
 ? ?// get、set
?
 ? ?@Override
 ? ?protected Object clone() throws CloneNotSupportedException {
 ? ? ? ?return super.clone();
 ?  }
}
?
public class Main {
 ? ?public static void main(String[] args) throws CloneNotSupportedException {
 ? ? ? ?Data data1 = new Data(10);
?
 ? ? ? ?// 使用浅拷贝克隆对象
 ? ? ? ?Data data2 = (Data) data1.clone();
?
 ? ? ? ?System.out.println(data1.getValue()); ?// 输出: 10
 ? ? ? ?System.out.println(data2.getValue()); ?// 输出: 10
?
 ? ? ? ?// 修改原始对象的值
 ? ? ? ?data1.setValue(20);
?
 ? ? ? ?System.out.println(data1.getValue()); ?// 输出: 20
 ? ? ? ?System.out.println(data2.getValue()); ?// 输出: 10 (没有共享引用)
 ?  }
}

文章来源:https://blog.csdn.net/weixin_46739493/article/details/132781125
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。