一、简介
一个引用对象一般来说由两个部分组成:一个具名的Handle,也就是我们所说的声明(如变量)和一个内部(不具名)的对象,也就是具名Handle的内部对象。它在Manged Heap(托管堆)中分配,一般由新增引用对象的New方法是进行创建。深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。
二、父类和子类
2.1 动物类
定义了变量名称和性别;提供了两个抽象方法吃和睡觉,并且实现了序列化接口。如果父类没有实现序列化接口,那么子类就不能获得父类相应的属性。
Animal.java
package com.alian.csdn.clone;
import java.io.Serializable;
public abstract class Animal implements Serializable {
public String name;
public String sex;
public abstract void eat();
public abstract void sleep();
public Animal() {
}
public Animal(String name, String sex) {
this.name = name;
this.sex = sex;
}
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;
}
}
2.2 狗类
继承了动物类,实现了序列化接口。增加自身的属性,如腿的数量,品种。
Dog.java
package com.alian.csdn.clone;
import java.io.Serializable;
public class Dog extends Animal implements Serializable {
private int leg;
private String breeds;
public Dog() {
}
public Dog(String name, String sex, int leg, String breeds) {
super(name, sex);
this.leg = leg;
this.breeds = breeds;
}
public int getLeg() {
return leg;
}
public void setLeg(int leg) {
this.leg = leg;
}
public String getBreeds() {
return breeds;
}
public void setBreeds(String breeds) {
this.breeds = breeds;
}
@Override
public void eat() {
System.out.println("只吃肉骨头");
}
@Override
public void sleep() {
System.out.println("睡觉要吹空调");
}
}
三、测试(有核心方法)
CloneObjectTest.java
package com.alian.csdn.clone;
import java.io.*;
public class CloneObjectTest {
public static void main(String[] args) throws Exception {
Dog sourceDog = new Dog("二毛", "雄性", 4, "拉布拉多");
Dog dog = clone(sourceDog);
System.out.println("姓名:" + dog.getName());
System.out.println("性别:" + dog.getSex());
System.out.println("腿:" + dog.getLeg() + "条");
System.out.println("品种:" + dog.getBreeds());
dog.eat();
dog.sleep();
}
private static <T extends Serializable> T clone(T obj) throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (T) ois.readObject();
}
}
运行结果:
姓名:二毛
性别:雄性
腿:4条
品种:拉布拉多
只吃肉骨头
睡觉要吹空调
注意:
被拷贝的类要实现序列化接口,如果同时需要获取父类的属性,父类也需要实现序列化接口;可以不调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法,和文件流不同,他们是基于内存的流,可以通过垃圾回收器清理对象释放资源。