克隆实现
Object类里有个clone方法,使用clone方法复制一个对象
克隆测试
public class Car {
private int color;
private String name;
private int[] gls;
private Object engine;
public void setColor(int color) {
this.color = color;
}
public void setName(String name) {
this.name = name;
}
public void setGls(int[] gls) {
this.gls = gls;
}
public void setEngine(Object engine) {
this.engine = engine;
}
public static void main(String[] args) throws CloneNotSupportedException {
Car car = new Car();
car.setColor(1);
car.setGls(new int[]{1, 2, 3, 4});
car.setName("daben");
car.setEngine(new Engine("asdf"));
Object clone = car.clone();
}
}
输出结果
Exception in thread "main" java.lang.CloneNotSupportedException: com.xwf.gx.design.clonetest.Car
at java.base/java.lang.Object.clone(Native Method)
at com.xwf.gx.design.clonetest.Car.main(Car.java:40)
实现方式:
Cloneable 接口标识可合法调用 clone() ,类似Serializable,RandomAccess 接口
public class Engine {
public String engineName;
public Engine(String engineName) {
this.engineName = engineName;
}
}
public class Car implements Cloneable {
public int color; //基本类型
public String name; //引用类型
public Engine engine; //引用类型
public void setColor(int color) {
this.color = color;
}
public void setName(String name) {
this.name = name;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Car car = new Car();
car.setColor(1);
car.setName("daben");
car.setEngine(new Engine("asdf"));
Car car2 = (Car) car.clone();
System.out.println(car);
System.out.println(car2);
System.out.println("car ? " + (car2 == car));
System.out.println("color ? " + (car2.color == car.color));
System.out.println("name ? " + (car2.name == car.name));
System.out.println("engine ? " + (car2.engine == car.engine));
System.out.println("1car color : " + car.color);
System.out.println("1car2 color : " + car2.color);
System.out.println("1car name : " + car.name);
System.out.println("1car2 name : " + car2.name);
System.out.println("1car engine : " + car.engine);
System.out.println("1car2 engine : " + car2.engine);
car2.name = "baoma";
car2.color = 2;
car2.engine.engineName = "new name";
System.out.println("2car color : " + car.color);
System.out.println("2car2 color : " + car2.color);
System.out.println("2car name : " + car.name);
System.out.println("2car2 name : " + car2.name);
System.out.println("2car engine : " + car.engine.engineName);
System.out.println("2car2 engine : " + car2.engine.engineName);
}
结果:
com.xwf.gx.design.clonetest.Car@2f7c7260
com.xwf.gx.design.clonetest.Car@2d209079
car ? false
color ? true
name ? true
engine ? true
1car color : 1
1car2 color : 1
1car name : daben
1car2 name : daben
1car engine : com.xwf.gx.design.clonetest.Engine@6bdf28bb
1car2 engine : com.xwf.gx.design.clonetest.Engine@6bdf28bb
2car color : 1
2car2 color : 2
2car name : daben
2car2 name : baoma
2car engine : new name
2car2 engine : new name
实现clone接口,运行正常。
浅克隆
上面例子就是浅克隆
输出结果总结一下:
对象复制成功 car 和 car2 是两个不同的对象
基本类型color 值复制
引用类型name engine 复制的是引用,指向的还是car里的对象
深度克隆实现方式
既然引用类型无法被完全克隆,那将引用类型也实现Cloneable接口重写clone方法
public class Engine implements Cloneable {
public String engineName;
public Engine(String engineName) {
this.engineName = engineName;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Car implements Cloneable {
public int color; //基本类型
public String name; //引用类型
public Engine engine; //引用类型
public void setColor(int color) {
this.color = color;
}
public void setName(String name) {
this.name = name;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Car car2 = (Car) super.clone();
car2.engine = (Engine) engine.clone();
return car2;
}
public static void main(String[] args) throws CloneNotSupportedException {
Car car = new Car();
car.setColor(1);
car.setName("daben");
car.setEngine(new Engine("asdf"));
Car car2 = (Car) car.clone();
System.out.println(car);
System.out.println(car2);
System.out.println("car ? " + (car2 == car));
System.out.println("color ? " + (car2.color == car.color));
System.out.println("name ? " + (car2.name == car.name));
System.out.println("engine ? " + (car2.engine == car.engine));
System.out.println("1car color : " + car.color);
System.out.println("1car2 color : " + car2.color);
System.out.println("1car name : " + car.name);
System.out.println("1car2 name : " + car2.name);
System.out.println("1car engine : " + car.engine);
System.out.println("1car2 engine : " + car2.engine);
car2.name = "baoma";
car2.color = 2;
car2.engine.engineName = "new name";
System.out.println("2car color : " + car.color);
System.out.println("2car2 color : " + car2.color);
System.out.println("2car name : " + car.name);
System.out.println("2car2 name : " + car2.name);
System.out.println("2car engine : " + car.engine.engineName);
System.out.println("2car2 engine : " + car2.engine.engineName);
}
/*System.out.println(car.engine);
System.out.println(car2.engine);
System.out.println(car);
System.out.println(car2);
car2.setColor(33);
System.out.println(car.color);
System.out.println(car2.color);
//System.out.println(car.engine == car2.engine);
// System.out.println(Objects.equals(car.color, car2.color));
// System.out.println(Objects.equals(car.engine, car2.engine));
// System.out.println(Objects.equals(car.gls, car2.gls));
// System.out.println(Objects.equals(car.name, car2.name));
car2.engine.engineName = "1";
System.out.println(car.engine.engineName);
System.out.println(car2.engine.engineName);*/
}
执行结果:
com.xwf.gx.design.clonetest.Car@2f7c7260
com.xwf.gx.design.clonetest.Car@2d209079
car ? false
color ? true
name ? true
engine ? false
1car color : 1
1car2 color : 1
1car name : daben
1car2 name : daben
1car engine : com.xwf.gx.design.clonetest.Engine@6bdf28bb
1car2 engine : com.xwf.gx.design.clonetest.Engine@6b71769e
car ? false
color ? false
name ? false
engine ? false
2car color : 1
2car2 color : 2
2car name : daben
2car2 name : baoma
2car engine : asdf
2car2 engine : new name
输出结果总结一下:
对象复制成功 car 和 car2 是两个不同的对象
基本类型color 值复制
引用类型name engine 变成了不同的对象
深度克隆可以把引用类型的变量也复制一份,不和原对象公用一个对象。