转载自:https://blog.csdn.net/leixiaotao_java/article/details/69525224
1.概念
a.Object的clone方法:
protected native Object clone() throws CloneNotSupportedException
b.clone方法重写原则:
- x.clone() != x为 true
- x.clone().getClass() == x.getClass()
- x.clone().equals(x)为 true
- 实现
Cloneable
接口(若不实现调用clone()时会抛出CloneNotSupportedException
)
c.Object的clone()方法为浅复制。
java克隆的2种方法
1.调用clone方法
- 对象实现Cloneable接口并重写Object类中的clone()方法(调用Object的clone()实现,浅克隆方式);
(a)用户信息
public class Person implements Cloneable{
private String name;
private String sex;
private Phone phone;
/**
* 实现Cloneable接口,并重写clone方法
*/
@Override
protected Object clone(){
Person p=null;
try {
/**
* 若要实现深克隆,此处就必须将对象中所有的复合数据类型统统单独复制拷贝一份,
* 但是实际开发中,无法确定对象中复合数据的种类和个数,
* 因此一般不采用此种方式实现深克隆
*/
p = (Person) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
public Person(String name, String sex, Phone phone) {
super();
this.name = name;
this.sex = sex;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Phone getPhone() {
return phone;
}
public void setPhone(Phone phone) {
this.phone = phone;
}
@Override
public String toString() {
return "[name=" + name + ", sex=" + sex + ", phone=" + phone
+ "]";
}
}
(b)手机信息
public class Phone{
private String number;
private String area;
public Phone(String number, String area) {
super();
this.number = number;
this.area = area;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
@Override
public String toString() {
return "[number=" + number + ", area=" + area + "]";
}
}
(c)测试代码
public static void main(String[] args) {
Person p=new Person("雷小涛", "man", new Phone("123456", "四川成都"));
Person p2=(Person) p.clone();
System.out.println("p:"+p.toString());
System.out.println("p2:"+p2.toString());
p2.setName("leixiaotao");
p2.getPhone().setArea("四川乐山");
System.out.println("-------其中一个对象修改值过后-------");
System.out.println("p:"+p.toString());
System.out.println("p2:"+p2.toString());
}
- 实现Cloneable接口,重写clone()方法,实现深克隆(
不
调用Object的clone()实现,深克隆方式)
2.序列化(深度拷贝
)
序列化一个对象,该类必须实Serializable
标记性接口
(a)用户信息类
public class Person implements Serializable{
private static final long serialVersionUID = -3936148364278781089L;
private String name;
private String sex;
private Phone phone;
public Person(String name, String sex, Phone phone) {
super();
this.name = name;
this.sex = sex;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Phone getPhone() {
return phone;
}
public void setPhone(Phone phone) {
this.phone = phone;
}
@Override
public String toString() {
return "[name=" + name + ", sex=" + sex + ", phone=" + phone
+ "]";
}
}
(b)手机信息类
public class Phone implements Serializable{
private static final long serialVersionUID = -4482468804013490322L;
private String number;
private String area;
public Phone(String number, String area) {
super();
this.number = number;
this.area = area;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
@Override
public String toString() {
return "[number=" + number + ", area=" + area + "]";
}
}
(c)CloneUtil工具类
public class CloneUtil {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T object) throws Exception{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(object);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
// 此处不需要释放资源,说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
return (T) ois.readObject();
}
}
(d)测试代码
public static void main(String[] args) throws Exception {
Person p=new Person("雷小涛", "man", new Phone("123456", "四川成都"));
// Person p2=(Person) p.clone();
Person p2=CloneUtil.clone(p);
System.out.println("p:"+p.toString());
System.out.println("p2:"+p2.toString());
p2.setName("leixiaotao");
p2.getPhone().setArea("四川乐山");
System.out.println("-------其中一个对象修改值过后-------");
System.out.println("p:"+p.toString());
System.out.println("p2:"+p2.toString());
}