Java中的clone方法实例详解
什么是clone方法
clone()
方法是Object类提供的一个protected方法,实现对象的复制(克隆)。通过调用对象的clone()方法返回一个复制后的对象,对象的类型与原对象的类型相同。
clone方法的实现
-
Object中的clone方法是原生方法,性能非常高。因此,我们在实现
clone
方法时要重写clone
方法,并调用super.clone()
方法实现克隆。 -
如果需要深层次的复制,则需要重写
clone
方法,并且对需要克隆的属性进行深度克隆。
代码示例
浅拷贝示例
下面是一个浅拷贝示例
public class Person implements Cloneable{
private String name;
private int age;
private Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + address +
'}';
}
public static void main(String[] args) {
Address a = new Address();
a.setAddress("China");
Person p1 = new Person("张三", 20, a);
Person p2 = (Person) p1.clone();
System.out.println(p1);
System.out.println(p2);
a.setAddress("USA");
System.out.println(p1);
System.out.println(p2);
}
}
class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
在上述示例中,我们创建了一个Person类,其中包含了一个address属性,类型为自定义Address类对象。Person类实现了Cloneable接口,并重写了clone方法。在main函数中,我们创建了一个Person对象p1,并将其浅拷贝给p2。然后,我们修改了address属性的值,并打印出了p1和p2的地址信息。运行结果如下所示:
Person{name='张三', age=20, address=Address{address='China'}}
Person{name='张三', age=20, address=Address{address='China'}}
Person{name='张三', age=20, address=Address{address='USA'}}
Person{name='张三', age=20, address=Address{address='USA'}}
从结果中可以看到,虽然我们修改了a的值(在地址信息中,将China改为USA),但是p2还是指向了原先的地址。这是因为在浅拷贝中,只有基本数据类型和String类型的属性会进行值传递,而非基本数据类型和String类型的属性会被当作引用传递。在浅拷贝中,复制后的对象与被复制对象共用一份成员变量,因此,当成员变量值发生改变时,会影响另一个对象。
深拷贝示例
下面是一个深拷贝示例:
public class Person implements Cloneable{
private String name;
private int age;
private Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
public Object clone() {
try {
Person person = (Person) super.clone();
person.address = (Address) address.clone();
return person;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + address +
'}';
}
public static void main(String[] args) {
Address a = new Address();
a.setAddress("China");
Person p1 = new Person("张三", 20, a);
Person p2 = (Person) p1.clone();
System.out.println(p1);
System.out.println(p2);
a.setAddress("USA");
System.out.println(p1);
System.out.println(p2);
}
}
class Address implements Cloneable{
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
在上述示例中,我们在Person类中对需要深度拷贝的引用类型属性进行了深度拷贝。其中,Address类也实现了Cloneable接口,并重写了clone方法。在Main函数中,我们又创建了一个Address类型的对象a,并将其传入Person类的构造函数。通过打印a的信息可以看出,a地址为China。然后,我们将p1浅拷贝给p2,打印出p1和p2的信息,再次通过改变a的地址为USA打印出p1和p2的信息。运行结果如下所示:
Person{name='张三', age=20, address=Address{address='China'}}
Person{name='张三', age=20, address=Address{address='China'}}
Person{name='张三', age=20, address=Address{address='China'}}
Person{name='张三', age=20, address=Address{address='USA'}}
从结果中可以看到,我们通过修改a的地址为USA后,p1和p2的address属性的地址都发生了改变,因为他们两个都拥有一个自己的Address对象。因此,在进行深拷贝时,需要对被拷贝对象的引用类型属性进行深度拷贝。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的clone方法实例详解 - Python技术站