1、clone方法
拷贝对象分为浅拷贝和深拷贝,参考官方文档
创建并且返回一个对象的副本。确切的说这个副本要取决于这个对象的类(如果这个对象的类没有实现接口Cloneable,则无法拷贝)。正常来说所有的对象都可以使用这个方法。
一般来说,被这个方法返回(被克隆出来的对象)的对象要独立于被克隆的对象,为了实现这种独立性,这个被返回的对象的某些属性在返回之前有必要去修改。通常,在克隆这些内部具有深层结构的可变对象的时候要使用他们的副本的引用来替换他们的引用。如果一个类包含的只是原始数据(基本数据类型)或者是不可改变对象的引用,那么这个被克隆的对象的属性不需要修改。如果一个类没有实现“Cloneable”接口,在克隆对象的时候会抛出“CloneNotSupportedException”
小结1
如果的对象里面的某些属性是可变引用类型的数据 (比如我们自己定义类),那么这样的属性的值需要我们去改变,将这些类型的属性继续被克隆。
浅拷贝和深拷贝
问题
package com.baidu.vo;
import java.io.Serializable;
import java.util.Scanner;
//雇员表简单Java类
public class Emp implements Cloneable {
private String ename;
private Integer empno;
private School school;
public Emp(String ename, Integer empno, School school) {
this.ename = ename;
this.empno = empno;
this.school = school;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public Integer getEmpno() {
return empno;
}
public void setEmpno(Integer empno) {
this.empno = empno;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
package com.baidu.vo;
public class School {
private String sname;
public School(String sname) {
this.sname = sname;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
}
package com.CoderLB;
import com.baidu.vo.Emp;
import com.baidu.vo.School;
public class Test {
public static void main(String[] args) throws Exception {
Emp emp = new Emp("李四", 10089, new School("南京大学"));
//拷贝对象的信息,看看是否会影响克隆的对象
Emp emp1 = (Emp) emp.clone();
System.out.println(emp1.getEname() + " " + emp1.getEmpno() + " " + emp1.getSchool().getSname());
//修改原来对象
emp.setEname("Jack");
emp.setEmpno(10099);
emp.getSchool().setSname("东南大学");
System.out.println(emp1.getEname() + " " + emp1.getEmpno() + " " + emp1.getSchool().getSname());
}
}
输出:
李四 10089 南京大学
李四 10089 东南大学
发现了我们自己定义的类型在原对象中被修改的时候,拷贝后的对象中的该属性也被修改了,这样的拷贝就币具有独立性,这种现象叫做浅拷贝 (School类有自己的内部深层结构)
深拷贝
package com.baidu.vo;
public class School implements Cloneable{
private String sname;
public School(){}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public School(String sname) {
this.sname = sname;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
}
package com.baidu.vo;
import java.io.Serializable;
import java.util.Scanner;
//雇员表简单Java类
public class Emp implements Cloneable {
private String ename;
private Integer empno;
private School school;
public Emp(String ename, Integer empno, School school) {
this.ename = ename;
this.empno = empno;
this.school = school;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public Integer getEmpno() {
return empno;
}
public void setEmpno(Integer empno) {
this.empno = empno;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
public Object clone() throws CloneNotSupportedException {
Emp emp = (Emp) super.clone();
//克隆学校的对象
emp.school=(School)emp.getSchool().clone();
return emp;
}
}
package com.CoderLB;
import com.baidu.vo.Emp;
import com.baidu.vo.School;
public class Test {
public static void main(String[] args) throws Exception {
Emp emp = new Emp("李四", 10089, new School("南京大学"));
//拷贝对象的信息,看看是否会影响克隆的对象
Emp emp1 = (Emp) emp.clone();
System.out.println(emp1.getEname() + " " + emp1.getEmpno() + " " + emp1.getSchool().getSname());
//修改原来对象
emp.setEname("Jack");
emp.setEmpno(10099);
emp.getSchool().setSname("东南大学");
System.out.println(emp1.getEname() + " " + emp1.getEmpno() + " " + emp1.getSchool().getSname());
}
}
输出:李四 10089 南京大学 李四 10089 南京大学
此时发现了School属性也独立了,因为School对象也被拷贝了,这就是深拷贝的操作。