关于java对象复制

来源:java认证发布时间:2012-11-12 13:12:36java认证视频

  class CloneB implements Cloneable{

  public int aInt;

  public UnCloneA unCA = new UnCloneA(111);

  public Object clone(){

  CloneB o = null;

  try{

  o = (CloneB)super.clone();

  }catch(CloneNotSupportedException e){

  e.printStackTrace();

  }

  o.unCA = (UnCloneA)unCA.clone();

  return o;

  }

  }

  public class CloneMain {

  public static void main(String[] a){

  CloneB b1 = new CloneB();

  b1.aInt = 11;

  System.out.println("before clone,b1.aInt = "+ b1.aInt);

  System.out.println("before clone,b1.unCA = "+ b1.unCA);

  CloneB b2 = (CloneB)b1.clone();

  b2.aInt = 22;

  b2.unCA.doubleValue();

  System.out.println("=================================");

  System.out.println("after clone,b1.aInt = "+ b1.aInt);

  System.out.println("after clone,b1.unCA = "+ b1.unCA);

  System.out.println("=================================");

  System.out.println("after clone,b2.aInt = "+ b2.aInt);

  System.out.println("after clone,b2.unCA = "+ b2.unCA);

  }

  }

  /** RUN RESULT:

  before clone,b1.aInt = 11

  before clone,b1.unCA = 111

  =================================

  after clone,b1.aInt = 11

  after clone,b1.unCA = 111

  =================================

  after clone,b2.aInt = 22

  after clone,b2.unCA = 222

  */

  可以看出,现在b2.unCA的改变对b1.unCA没有产生影响。此时b1.unCA与b2.unCA指向了两个不同的UnCloneA实例,而且在CloneB b2 = (CloneB)b1.clone();调用的那一刻b1和b2拥有相同的值,在这里,b1.i = b2.i = 11。

  要知道不是所有的类都能实现深度clone的。例如,如果把上面的CloneB类中的UnCloneA类型变量改成StringBuffer类型,看一下JDK API中关于StringBuffer的说明,StringBuffer没有重载clone()方法,更为严重的是StringBuffer还是一个final类,这也是说我们也不能用继承的办法间接实现StringBuffer的clone。如果一个类中包含有StringBuffer类型对象或和StringBuffer相似类的对象,我们有两种选择:要么只能实现影子clone,要么就在类的clone()方法中加一句(假设是SringBuffer对象,而且变量名仍是unCA): o.unCA = new StringBuffer(unCA.toString()); //原来的是:o.unCA = (UnCloneA)unCA.clone();

  还要知道的是除了基本数据类型能自动实现深度clone以外,String对象是一个例外,它clone后的表现好象也实现了深度clone,虽然这只是一个假象,但却大大方便了我们的编程。

  通过以上我们可以看出在某些情况下,我们可以利用clone方法来实现对象只见的复制,但对于比较复杂的对象(比如对象中包含其他对象,其他对象又包含别的对象.....)这样我们必须进行层层深度clone,每个对象需要实现cloneable接口,比较麻烦,那就继续学习下一个序列化方法。

  2 对象序列化

  所谓对象序列化就是将对象的状态转换成字节流,以后可以通过这些值再生成相同状态的对象。这个过程也可以通过网络实现,可以先在Windows机器上创建一个对象,对其序列化,然后通过网络发给一台Unix机器,然后在那里准确无误地重新“装配”。是不是很神奇。

  也许你会说,只了解一点点,但从来没有接触过,其实未必如此。RMI、Socket、JMS、EJB你总该用过一种吧,彼此为什么能够传递Java对象,当然都是对象序列化机制的功劳。

  第一次使用Java的对象序列化是做某项目,当时要求把几棵非常复杂的树(JTree)及相应的数据保存下来(就是我们常用的保存功能),以便下次运行程序时可以继续上次的操作。

  那时XML技术在网上非常的热,而且功能也强大,再加上树的结构本来就和XML存储数据的格式很像。作为一项对新技术比较有兴趣的我当然很想尝试一下。不过经过仔细分析,发现如果采用XML保存数据,后果真是难以想象:哪棵树的哪个节点被展开、展开到第几级、节点当前的属性是什么。真是不知该用A、B、C还是用1、2、3来表示。

  还好,发现了Java的对象序列化机制,问题迎刃而解,只需简单的将每棵树的根节点序列化保存到硬盘上,下次再通过反序列化后的根节点就可以轻松的构造出和原来一模一样的树来。

  其实保存数据,尤其是复杂数据的保存正是对象序列化的典型应用。最近另一个项目就遇到了需要对非常复杂的数据进行存取,通过使用对象的序列化,问题同样化难为简。

  对象的序列化还有另一个容易被大家忽略的功能就是对象复制(Clone),Java中通过Clone机制可以复制大部分的对象,但是众所周知,Clone有深层Clone和浅层Clone,如果你的对象非常非常复杂,假设有个100层的Collection(夸张了点),如果你想实现深层Clone,真是不敢想象,如果使用序列化,不会超过10行代码就可以解决。

  还有就是Swing组件,如果你有两个很象很象(或是一模一样)的比较难以构造的Swing组件,你该怎么办,也许你想到了Clone,但是偏偏Java的Swing组件没有提供Clone方法。别急,使用序列化,6行代码搞定:

  ByteArrayOutputStream

  byteOut = new ByteArrayOutputStream();

  ObjectOutputStream out

  = new ObjectOutputStream(byteOut);

  out.writeObject(combo);

  ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());

  ObjectInputStream in

  =new ObjectInputStream(byteIn);

  JComboBox comb2 = (JComboBox)in.readObject();

  虽然Java的序列化非常简单、强大,但是要用好,还有很多地方需要注意。比如曾经序列化了一个对象,可由于某种原因,该类做了一点点改动,然后重新被编译,那么这时反序列化刚才的对象,将会出现异常。

  你可以通过添加serialVersionUID属性来解决这个问题。如果你的类是个单态(Singleton)类,是否允许用户通过序列化机制复制该类,如果不允许你需要谨慎对待该类的实现。

  /**

  * Clone Object

  * @param obj

  * @return

  * @throws Exception

  */

  private Object cloneObject(Object obj) throws Exception{

  ByteArrayOutputStream byteOut = new ByteArrayOutputStream();

  ObjectOutputStream out = new ObjectOutputStream(byteOut);

  out.writeObject(obj);

  ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());

  ObjectInputStream in =new ObjectInputStream(byteIn);

  return in.readObject();

  }

上一页12下一页

视频学习

我考网版权与免责声明

① 凡本网注明稿件来源为"原创"的所有文字、图片和音视频稿件,版权均属本网所有。任何媒体、网站或个人转载、链接转贴或以其他方式复制发表时必须注明"稿件来源:我考网",违者本网将依法追究责任;

② 本网部分稿件来源于网络,任何单位或个人认为我考网发布的内容可能涉嫌侵犯其合法权益,应该及时向我考网书面反馈,并提供身份证明、权属证明及详细侵权情况证明,我考网在收到上述法律文件后,将会尽快移除被控侵权内容。

最近更新

社区交流

考试问答