Java Clone方法之懒人实现
Java Clone方法之懒人实现
在Java的Object类中定义了(protected)clone()方法,如果自己的类需要clone方法的话需要实现Cloneable接口,并重写clone()方法和将方法访问级别改为(public)。但是如果自己的类如果属性比较多,重写clone方法还是会花去不少时间,更重要的是以后增加或者删除属性的时候也要相应修改clone方法,总的来说还是比较麻烦的。
这里如果对性能不太计较的话,其实可以有一个简单快速的方法实现clone方法,就是使用Java语言的序列化功能来实现clone方法,如下:
以下是几个测试的Bean类
- import java.io.Serializable;
- public class A implements Serializable {
- private static final long serialVersionUID = 1L;
- private String name;
- private B b;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public B getB() {
- return b;
- }
- public void setB(B b) {
- this.b = b;
- }
- @Override
- public Object clone() {
- return CloneUtil.clone(this);
- }
- }
- import java.io.Serializable;
- public class B implements Serializable {
- private static final long serialVersionUID = 1L;
- private String name;
- private C c;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public C getC() {
- return c;
- }
- public void setC(C c) {
- this.c = c;
- }
- @Override
- public Object clone() {
- return CloneUtil.clone(this);
- }
- }
- import java.io.Serializable;
- public class C implements Serializable, Cloneable {
- private static final long serialVersionUID = 1L;
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public Object clone() {
- return CloneUtil.clone(this);
- }
- }
Clone工具类,这个类负责通过序列化和反序列化做到对一个对象的clone
- import java.io.*;
- public class CloneUtil {
- public static Object clone(Object obj) {
- Object anotherObj = null;
- byte[] bytes;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = null;
- try {
- oos = new ObjectOutputStream(baos);
- oos.writeObject(obj);
- bytes = baos.toByteArray();
- } catch(IOException ex) {
- throw new RuntimeException(ex.getMessage(), ex);
- } finally {
- if (oos != null) {
- try {
- oos.close();
- } catch (IOException e) {
- // ignore me
- }
- }
- }
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- ObjectInputStream ois = null;
- try {
- ois = new ObjectInputStream(bais);
- anotherObj = ois.readObject();
- } catch(IOException ex) {
- throw new RuntimeException(ex.getMessage(), ex);
- } catch(ClassNotFoundException ex) {
- throw new RuntimeException(ex.getMessage(), ex);
- } finally {
- if (ois != null) {
- try {
- ois.close();
- } catch (IOException e) {
- // ignore me
- }
- }
- }
- return anotherObj;
- }
- }
测试类
- public class Test {
- public static void main(String[] args) throws Exception {
- A a = new A();
- B b = new B();
- C c = new C();
- c.setName("ccc");
- b.setName("bbb");
- b.setC(c);
- a.setName("aaa");
- a.setB(b);
- System.out.println("a: " + a);
- System.out.println("a: " + a.getName());
- System.out.println("a: " + a.getB().getName());
- System.out.println("a: " + a.getB().getC().getName());
- A anotherA = (A)a.clone();
- System.out.println("anotherA: " + anotherA);
- System.out.println("anotherA: " + anotherA.getName());
- System.out.println("anotherA: " + anotherA.getB().getName());
- System.out.println("anotherA: " + anotherA.getB().getC().getName());
- System.out.println("=== change properties of a ===");
- a.setName("aaaaa");
- a.getB().setName("bbbbb");
- a.getB().getC().setName("ccccc");
- System.out.println("a: " + a);
- System.out.println("a: " + a.getName());
- System.out.println("a: " + a.getB().getName());
- System.out.println("a: " + a.getB().getC().getName());
- System.out.println("anotherA: " + anotherA);
- System.out.println("anotherA: " + anotherA.getName());
- System.out.println("anotherA: " + anotherA.getB().getName());
- System.out.println("anotherA: " + anotherA.getB().getC().getName());
- System.out.println("=== change properties of anotherA ===");
- anotherA.setName("aaaa");
- anotherA.getB().setName("bbbb");
- anotherA.getB().getC().setName("cccc");
- System.out.println("a: " + a);
- System.out.println("a: " + a.getName());
- System.out.println("a: " + a.getB().getName());
- System.out.println("a: " + a.getB().getC().getName());
- System.out.println("anotherA: " + anotherA);
- System.out.println("anotherA: " + anotherA.getName());
- System.out.println("anotherA: " + anotherA.getB().getName());
- System.out.println("anotherA: " + anotherA.getB().getC().getName());
- }
- }
运行测试类可以看到结果。这里通过代码可以看出这种实现还是有一些限制的:
1. 自己的bean必须实现Serializable接口;
2. 由于这种实现使用了序列化,所以性能不是很好,所以如果对象太多,不建议使用;
3. 由于在序列化的过程中没有将对象序列化到文件中,而是保留在了内存数组中,所以如果对象太大的话,会造成比较大的内存使用,需要注意。
评论暂时关闭