Object类中的clone()方法是Java中的一个重要方法,这个方法可以返回一个对象的“浅拷贝”,也就是对原对象中的内容进行复制,但不会复制原对象指向的对象。深入掌握这个方法,将对Java工程师的职业发展带来很大帮助。
一、clone()方法的使用和作用
clone()方法的作用是生成一个与原对象相同的新对象。使用clone()方法时,需要实现Cloneable接口,否则会抛出CloneNotSupportedException异常。
以下是使用clone方法实现浅拷贝的示例:
class Person implements Cloneable{ private String name; private int age; private ArrayListskills; public Person(String name, int age, ArrayList skills) { this.name = name; this.age = age; this.skills = skills; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { ArrayList skills = new ArrayList(); skills.add("Java"); skills.add("Spring"); Person person = new Person("Tom", 23, skills); Person cloned = (Person) person.clone(); System.out.println(person == cloned); //false System.out.println(person.getName() == cloned.getName()); //true System.out.println(person.getSkills() == cloned.getSkills()); //true } }
从输出的结果可以看到,浅拷贝后,原对象和新对象指向的ArrayList对象是一个,但是Person对象不是同一个。
二、浅拷贝和深拷贝的区别
浅拷贝
clone()方法实现的是浅拷贝,也就是说,如果对象的属性是基本类型或不可变类型,可以实现一个副本,不影响原对象。但如果属性是可变对象,如ArrayList,浅拷贝只会拷贝引用,而不会将ArrayList中的值也进行拷贝,使得原对象与新对象的引用相同。
深拷贝
深拷贝则是对可变对象进行递归拷贝,最终生成一个新的对象,使得原对象与新对象没有任何关系,可以互不干扰。
以下是深拷贝的示例:
public class Person implements Cloneable { private String name; private int age; private ArrayListskills; public Person(String name, int age, ArrayList skills) { this.name = name; this.age = age; this.skills = skills; } @Override public Object clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.skills = (ArrayList ) this.skills.clone(); return cloned; } //省略访问器 } public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { ArrayList skills = new ArrayList(); skills.add("Java"); skills.add("Spring"); Person person = new Person("Tom", 23, skills); Person cloned = (Person) person.clone(); System.out.println(person == cloned); //false System.out.println(person.getSkills() == cloned.getSkills()); //false } }
从输出结果中,可以看出原对象与克隆对象没有任何关系,拥有自己独立的ArrayList对象。
三、实现clone()方法需要注意的细节
1、需要实现Cloneable接口
在使用clone()方法之前,需要实现Cloneable接口,否则会抛出CloneNotSupportedException异常。
2、需要重写clone()方法
重写clone()方法时,需要注意clone()方法是protected类型,需要使用public类型覆盖这个方法,并且要调用super.clone()方法来得到一个新的实例。返回的对象必须向下转型为正确的类型。
3、注意引用对象的问题
如果被克隆对象有引用类型的属性时,可以通过new一个新的对象进行深拷贝。
除此之外,还可以使用序列化实现深度拷贝,在序列化后再反序列化得到一个新的对象。
四、总结
深入掌握Object.clone()方法,能够让我们更好的处理对象克隆时的问题,从而提高Java工程师的职业发展水平。越来越多的框架和库要求我们实现cloneable接口,因此,掌握clone()方法将对我们的工作带来帮助。