Java中的拷贝可以分为深拷贝(Deep Copy)、浅拷贝(Shallow Copy)和引用拷贝(Reference Copy)。它们之间的区别如下:
浅拷贝:
只复制对象本身,而不复制对象包含的子对象。新旧对象之间共享子对象的引用,即新对象和原始对象中的子对象指向同一个内存地址。
浅拷贝:使用clone()方法或者Object类的copy()方法。
深拷贝:
不仅复制对象本身,还要复制对象包含的所有子对象。新对象和原始对象所包含的子对象是相互独立的。
深拷贝:可以通过序列化和反序列化、递归遍历等方式来实现。
引用拷贝:
只复制对象的引用,而不复制对象本身。新旧对象之间共享同一个对象实例,即它们的引用指向同一个内存地址。
引用拷贝:直接将对象的引用赋值给另一个变量即可。
例如,以下代码演示了引用拷贝和浅拷贝的区别:
class Person {
public String name;
public int age;
}
public class CopyDemo {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "Alice";
p1.age = 20;
Person p2 = p1; // 引用拷贝
System.out.println(p1 == p2); // true, 引用相等
System.out.println(p1.name == p2.name); // true, 字符串常量池中的引用相同
System.out.println(p1.age == p2.age); // true, 基本数据类型的值相同
Person p3 = (Person)p1.clone(); // 浅拷贝
System.out.println(p1 == p3); // false, 引用不相等
System.out.println(p1.name == p3.name); // true, 字符串常量池中的引用相同
System.out.println(p1.age == p3.age); // true, 基本数据类型的值相同
}
}
在上面的代码中,p1和p2是两个对象的引用,它们指向同一个对象实例。在使用引用拷贝时,p2和p1共享同一个对象实例,所以它们的属性值相等,并且两个引用也是相等的。
而当使用浅拷贝时,p3是通过调用p1的clone()方法来复制p1的对象的。由于这种方式只是复制了对象本身,而没有复制对象包含的子对象,所以p1和p3引用不同的对象实例。但由于name属性的值是字符串常量,字符串常量池中只有一个实例,所以p1和p3的name属性指向同一个对象。但age是一个基本数据类型,不是一个对象,所以p1和p3的age属性值相等。
例如,以下代码演示了深拷贝和浅拷贝的区别:
public class Address implements Cloneable {
private String name;
@Override
public Address clone() {
try {
return (Address) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
public class Person implements Cloneable {
public String name;
public int age;
private Address address;
// 省略构造函数、Getter&Setter方法
@Override
public Person clone() {
try {
Person person = (Person) super.clone();
return person;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
//测试 :
Person person1=new Person(new Address("武汉"));
Person person1Copy=person1.clone(); // true
System.out.println(person1.getAddress()==person1Copy.getAddress());
从输出结构就可以看出, person1 的克隆对象和 person1 使用的仍然是同一个 Address 对象。
深拷贝
这里我们简单对 Person 类的 clone() 方法进行修改,连带着要把 Person 对象内部的 Address 对象一起复制。文章来源:https://www.toymoban.com/news/detail-410421.html
@Override
public Person clone(){
try{
Person person=(Person)super.clone();
person.setAddress(person.getAddress().clone());
return person;
}catch(CloneNotSupportedException e){
throw new AssertionError();
}
}
测试 :
Person person1 = new Person(new Address("武汉"));
Person person1Copy = person1.clone(); // false
System.out.println(person1.getAddress() == person1Copy.getAddress());
从输出结构就可以看出,虽然 person1 的克隆对象和 person1 包含的 Address 对象已经是不同的了。文章来源地址https://www.toymoban.com/news/detail-410421.html
到了这里,关于Java面试必备:深拷贝、浅拷贝、引用拷贝的区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!