一、clone方法的介绍
在Java中,clone()是一种用于对象复制的机制,它使得我们可以复制一个对象的所有属性,而不是只复制对象的引用。
在Object类中,我们可以看到有一个clone()方法:
public class Object { protected native Object clone() throws CloneNotSupportedException; }
该方法也是protected修饰的,意味着我们不能直接在外部调用它。为了使用clone()方法,我们需要遵守一些规则,并在对应的类中重写该方法。
二、使用clone方法需要遵循的规则
在使用clone()方法的过程中,我们需要遵循以下规则:
- 实现Cloneable接口:该接口是一个标记接口,用于告诉JVM该类可以被克隆。如果没有实现该接口,clone()方法会抛出CloneNotSupportedException异常。
- 重写clone()方法:由于clone()方法是Object类的protected方法,所以在对应的类中需要重写该方法并将访问修饰符设为public。
三、clone方法的拷贝方式
在Java中,clone()方法的拷贝方式分为浅拷贝和深拷贝两种方式。
1. 浅拷贝
当我们使用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; } public Object clone() throws CloneNotSupportedException { return super.clone(); } public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address("China"); Person p1 = new Person("张三", 20, address); Person p2 = (Person) p1.clone(); System.out.println(p1 == p2); // false System.out.println(p1.getAddress() == p2.getAddress()); // true } } class Address { private String country; public Address(String country) { this.country = country; } public String getCountry() { return country; } }
由于Person类的address成员变量是一个引用类型的成员变量,所以在浅拷贝时只会复制该成员变量的引用地址,从而会导致p1和p2的address成员变量指向同一个对象。
2. 深拷贝
与浅拷贝不同,深拷贝会对引用类型成员变量的内容进行拷贝,从而完全复制了一个新的对象。
示例代码如下:
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; } public Object clone() throws CloneNotSupportedException { Person p = (Person) super.clone(); p.address = (Address) address.clone(); return p; } public Address getAddress() { return address; } public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address("China"); Person p1 = new Person("张三", 20, address); Person p2 = (Person) p1.clone(); System.out.println(p1 == p2); // false System.out.println(p1.getAddress() == p2.getAddress()); // false } } class Address implements Cloneable { private String country; public Address(String country) { this.country = country; } public String getCountry() { return country; } public Object clone() throws CloneNotSupportedException { return super.clone(); } }
在Person类的clone()方法中,由于address是一个引用类型的成员变量,因此我们需要将address也进行clone()操作,以实现深拷贝。在Address类中也需要实现Cloneable接口并重写clone()方法。
四、clone方法的使用场景
clone()方法通常被用在以下场景中:
- 在某些场景下,我们需要根据一个对象来创建出另外一个对象,但是我们不希望修改源对象,这时候就可以使用clone()方法来复制一个对象。
- 在具体实现时,可以通过复制一个对象的方式来提高效率。例如,当我们需要对一个对象进行一些比较耗费时间的初始化操作时,可以先克隆一个该对象的副本,在副本上进行初始化操作,然后再将副本赋值给源对象。
总结
Java中的clone()方法提供了一种对象复制的机制,可以用于创建一个具有与原对象相同属性的新对象。在使用clone()方法时,我们需要遵循规则,重写该方法并实现深浅拷贝。