在Java的体系中,数据类型分为基本数据类型和引用数据类型。
基本数据类型包括byte,short,int,long,float,double,boolean,char 8种,其克隆可通过赋值运算实现,比如
int a = 1;
int b = a;
引用类型的克隆的实现方式有以下两种:
1)实现Cloneable接口,重写clone() 方法,修改clone() 方法的修饰符为public。其分为浅克隆和深克隆。
2) 实现Serializable接口,对实例进行序列化,通过二进制流反序列化。其为真正的克隆。
注:若类没实现Cloneable接口,调用对象的clone方法会抛出CloneNotSupportedException异常
二、重写clone实现克隆
克隆就是获得当前对象的副本,其与当前对象是内存地址不同的两个对象。
浅克隆指的是当前对象的实例成员为引用类型时,副本的该实例成员只是复制了其引用值,指向同一个对象。
深克隆则是对该引用指向的对象进行克隆,然后引用指向了该副本,指向不同的对象。
浅克隆导致了一个问题就是,对实例或克隆副本做出的改变会影响彼此,从而导致错误的结果,下面的例子可以说明:
汽车类 Car,包含一个引用类型成员brand:
/**
* Car类
* 实现Cloneable接口,重写clone方法
* @author zhangyj
*
*/
public class Car implements Cloneable{
//使用年限
private int year;
//品牌
private Brand brand;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public Brand getBrand() {
return brand;
}
public void setBrand(Brand brand) {
this.brand = brand;
}
//构造器
public Car(int year, Brand brand) {
this.year = year;
this.brand = brand;
}
/**
* 浅克隆,调用父类的clone方法
*/
@Override
public Object clone() {
Object obj = null;
try {
obj = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
/**
* 深克隆,其引用类型成员也要调用clone
* @return
*/
public Car deepClone() {
Car car = null;
try {
car = (Car)super.clone();
car.setBrand((Brand)brand.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return car;
}
@Override
public String toString() {
return "[year=" + year + ", brand=" + brand + "]";
}
}
/**
* 品牌类
* @author zhangyj
*
*/
class Brand implements Cloneable{
//名称
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() {
Object obj = null;
try {
obj = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
public Brand(String name) {
this.name = name;
}
@Override
public String toString() {
return "Brand [name=" + name + "]";
}
}
测试类 CarCloneTest :