关于Java复制对象的问题

来源:互联网 发布:eplan p8软件价格 编辑:程序博客网 时间:2024/05/22 21:06

    今天写一个很简单的背包数据结构的实现,却被一个小问题难住了。在add一个新元素的方法中,开始时我是这么写的:

  1. public boolean add(Object newEntry) {  
  2.     if (isBagFull())  
  3.         doubleCapacity();  
  4.     entry[size ++] = newEntry;  
  5.     return true;  
  6. }//end add  

    可是这是一种很不安全的写法。比如客户想把一个newEntry对象添加到两个背包中,那么这两个背包中的对象实际上是同一个对象。因此在add方法中最好能复制一份newEntry, 把让entry[size]引用newEntry的备份。

    而newEntry是Object 类型,不能直接调用newEntry.clone()返回一个备份。怎么办呢?在网上搜啊搜,才知道我的疑问来自于浅复制和深复制的概念及实现。有一篇文章已经说得很好了:Java中的深复制与浅复制 http://java.chinaitlab.com/oop/716567.html  。下面总结一下该文章的内容以及我的理解。

    浅复制就是引用不同而对象相同,深复制就是对象也不同。clone() 方法十分诡异,一个类要implements Clonable, 然后覆盖clone() 方法,在clone() 方法中调用super.clone(), 才能实现深复制。如果不实现Clonable接口,则仍然是浅复制。我认为此方法很麻烦,比如我想复制一个类对象,就得把这个类的所有域的类、域的类的域 的类...都搞成Clonable。更重要的是,这个方法解决不了当前的问题:我要复制一个Object。

    另一种深复制的方法是利用“序列化”。把对象写到一个Byte流中,再读出来,达到复制的效果:

  1. public static Object copy(Object oldObj){  
  2.         Object obj = null;  
  3.         try{  
  4.             //Write the object out to a byte array  
  5.             ByteArrayOutputStream bOut = new ByteArrayOutputStream();  
  6.             ObjectOutputStream oOut = new ObjectOutputStream(bOut);  
  7.             oOut.writeObject(oldObj);  
  8.             oOut.flush();  
  9.             oOut.close();  
  10.               
  11.             //Retrieve an input stream from the byte array and read a copy of the object back in  
  12.             ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());  
  13.             ObjectInputStream oIn = new ObjectInputStream(bIn);  
  14.             obj = oIn.readObject();  
  15.             oIn.close();  
  16.         }catch(IOException e){  
  17.             e.printStackTrace();  
  18.         }catch(ClassNotFoundException e){  
  19.             e.printStackTrace();  
  20.         }  
  21.         return obj;  

    啊哈,其实一个Object不就是一堆字节流吗,类的结构决定了“划分”字节流的方式,从而成了某个类的对象。

    通过这次折腾,发现自己Java学得太菜了,对引用的认识太浅。要走的路还很长,继续折腾吧!