在java中标识哪个类是可以克隆的,需要该类实现Cloneable接口,它是在java.lang包中自动导入的,是个空接口,只作为一个标识.假如一个Student类,属性成员都是基本类型或者不可变对象的引用(像String类型)的话,java浅表复制也不会出现问题,但是当Student类中含有一个属性是引用类型时,如Address类,则这种情况下浅表克隆的student对象与原来的student对象就拥有对Address成员属性相同的引用,当克隆的对象修改时,也会改变原来student对象的内容.如果想使得克隆出来的对象彻底获得独立性,就需要进行深度克隆.下面的代码是我学习clone方法时候自己写的"深度克隆",拿上来献丑了.
Student.java
package hyp;
public class Student implements Cloneable { private String id; private String name; private Address address; public Student(){ this("",""); address = null; } public Student(String id,String name){ this.id = id; this.name = name; this.address = new Address(); } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Student clone(){ Student stu = null; try { stu = (Student)super.clone(); Address address = this.getAddress(); Address newAddress = address.clone(); stu.setAddress(newAddress); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return stu; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
Address.java
package hyp;
public class Address implements Cloneable{ private String province; private String city; private String strict; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getStrict() { return strict; } public void setStrict(String strict) { this.strict = strict; } public Address clone(){ Address address = null; try { address = (Address)super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return address; } }
Main.java
package hyp;
public class Main {
/** * @param args */
public static void main(String[] args) { // TODO Auto-generated method stub Student stu1 = new Student("0004","David"); Address address = stu1.getAddress(); address.setProvince("Shandong"); address.setCity("Taian"); address.setStrict("Xintai"); System.out.println(stu1.getId()+" "+stu1.getName()+" "+address.getProvince() +" "+address.getCity()+" "+address.getStrict()); Student stu2 = null; stu2 = stu1.clone(); Address address2 = stu2.getAddress(); System.out.println(stu2.getId()+" "+stu2.getName()+" "+address2.getProvince() +" "+address2.getCity()+" "+address2.getStrict()); System.out.println("stu1="+stu1); System.out.println("stu2="+stu2); System.out.println("address="+address); System.out.println("address2="+address2); }
} 这样克隆的student对象在更改某一属性的时候就跟原来的母体没关系了,因为彼此的对象内容分配了不同的内存空间.另外查看JDK帮助文档,可以看到object类的clone方法是受保护的,是native的,我们知道,native方法的效率一般来说都是远高于java中的非native方法。这也说明了new一个对象,然后将原对象中的数据导入到新创建的对象中去的做法是多么愚蠢.