📅  最后修改于: 2020-04-01 06:13:35             🧑  作者: Mango
对象克隆是指创建对象的精确副本。它创建当前对象类的新实例,并使用该对象相应字段的内容初始化其所有字段。使用赋值运算符创建参考变量的副本
在Java中,没有运算符可以创建对象的副本。与C++不同,在Java中,如果我们使用赋值运算符,则它将创建引用变量副本而不是对象的副本。可以通过举例说明:
// Java 如果我们使用赋值运算符,则它将创建引用变量而不是对象的副本
import java.io.*;
// 测试代码
class Test
{
int x, y;
Test()
{
x = 10;
y = 20;
}
}
// 测试代码
class Main
{
public static void main(String[] args)
{
Test ob1 = new Test();
System.out.println(ob1.x + " " + ob1.y);
// Creating a new reference variable ob2
// pointing to same address as ob1
Test ob2 = ob1;
// Any change made in ob2 will be reflected
// in ob1
ob2.x = 100;
System.out.println(ob1.x+" "+ob1.y);
System.out.println(ob2.x+" "+ob2.y);
}
}
输出:
10 20
100 20
100 20
使用clone()方法创建副本
要复制其对象的类必须在其或其父类之一中具有公共克隆方法。
protected Object clone() throws CloneNotSupportedException
clone()方法的用法-浅拷贝
// Java程序展示clone()方法的用法-浅拷贝
import Java.util.ArrayList;
// 这个类的对象的引用,被包含在Test2中
class Test
{
int x, y;
}
// 包含Test对象的引用,实现了浅拷贝的clone
class Test2 implements Cloneable
{
int a;
int b;
Test c = new Test();
public Object clone() throws
CloneNotSupportedException
{
return super.clone();
}
}
// 测试代码
public class Main
{
public static void main(String args[]) throws
CloneNotSupportedException
{
Test2 t1 = new Test2();
t1.a = 10;
t1.b = 20;
t1.c.x = 30;
t1.c.y = 40;
Test2 t2 = (Test2)t1.clone();
// 创建一个t1的拷贝,传给t2
t2.a = 100;
// 改变t2的数据类型,不会反应到t1
t2.c.x = 300;
// 改变对象字段的类型,会被反应到t1和t2(浅拷贝)
System.out.println(t1.a + " " + t1.b + " " +
t1.c.x + " " + t1.c.y);
System.out.println(t2.a + " " + t2.b + " " +
t2.c.x + " " + t2.c.y);
}
}
输出:
10 20 300 40
100 20 300 40
在上面的示例中,t1.clone返回对象t1的浅拷贝。为了获得对象的深层副本,必须在获取副本后在克隆方法中进行某些修改。
深拷贝与浅拷贝对比:
浅拷贝易于制操作。在上面的示例中,我们创建了对象的浅拷贝。
clone()方法的用法–深度复制
// Java展示深拷贝clone()
import Java.util.ArrayList;
// 这个类的对象的引用,被包含在Test2中
class Test
{
int x, y;
}
// 包含Test对象的引用,实现了深拷贝的clone
class Test2 implements Cloneable
{
int a, b;
Test c = new Test();
public Object clone() throws
CloneNotSupportedException
{
// 把浅拷贝赋值给引用t
Test2 t = (Test2)super.clone();
t.c = new Test();
// 给字段c创建一个新的对象,并复制给浅拷贝,使之成为深拷贝
return t;
}
}
public class Main
{
public static void main(String args[]) throws
CloneNotSupportedException
{
Test2 t1 = new Test2();
t1.a = 10;
t1.b = 20;
t1.c.x = 30;
t1.c.y = 40;
Test2 t3 = (Test2)t1.clone();
t3.a = 100;
// t2的原始类型改变,不会反应到t1中
t3.c.x = 300;
// t2的原始类型改变,不会反应到t1中(深拷贝)
System.out.println(t1.a + " " + t1.b + " " +
t1.c.x + " " + t1.c.y);
System.out.println(t3.a + " " + t3.b + " " +
t3.c.x + " " + t3.c.y);
}
}
输出:
10 20 30 40
100 20 300 0
在上面的示例中,我们可以看到已经为Test类分配了一个新对象来复制将在clone方法中返回的对象,由于此t3将获得对象t1的深层副本。因此,t3对“ c”对象字段所做的任何更改都不会反映在t1中。
克隆clone方法的优点: