Java程序设计与应用开发(第3版)
上QQ阅读APP看书,第一时间看更新

3.5 对象复制

假设我们需要对一个对象进行复制,怎么办呢?很多读者会想到赋值,例如:obj2=obj1。但是这个方法实际上并没有复制对象,而仅仅是建立一个新的对象引用,在执行这个操作后仍然只有一个对象,新建对象引用obj2也指向了对象引用obj1所指的对象。

本节介绍一个极其有用的方法Object.clone(),实现对象的复制。

既然clone是类Object中的一个方法,那么它能否像toString()这些方法一样,直接调用呢?我们来看下面这个例子。

例3.15 CloneDemo.java

     class AnObject{
       private int x;
         public AnObject(int x){
           this.x =x;
         }
         public int getX(){
           return x;
         }
     }
     public class CloneDemo{
       public static void main(String args[]){
         AnObject obj1 = new  AnObject(100);
         AnObject obj2 = (AnObject)obj1.clone();
         System.out.println("obj1 locate at "+obj1+" x="+obj1.getX());
         System.out.println("obj2 locate at "+obj2+" x="+obj2.getX());
       }
     }

上面的代码会引发编译错误。查阅Java API文档,我们会发现:Object.clone()是一个protected方法,因此不能直接调用clone()方法。我们将类AnObject修改如下:

     class AnObject{
       private int x;
       public AnObject(int x) {
         this.x =x;
       }
       public int getX(){
         return x;
       }
       public Object clone(){
         try{
           return super.clone();
         }catch(CloneNotSupportedException e){
           e.printStackTrace();
           return null;
         }
       }
     }

修改后的类AnObject定义了自己的clone()方法,它扩展Object.clone()方法。虽然CloneDemo.java可以编译,但是,当运行它时会抛出一个CloneNotSupportedException异常。通过阅读Java API文档我们发现,还必须让那些包含clone()方法的类实现Cloneable接口。代码如下:

     class AnObject implements Cloneable{
       private int x;
       public AnObject(int x){
         this.x =x;
       }
       public int getX(){
         return x;
       }
       public Object clone(){
         try{
            return super.clone();
         }catch (CloneNotSupportedException e){
            e.printStackTrace();
            return null;
         }
       }
     }

再次编译并运行CloneDemo.java,得到:

     obj1 locate at AnObject@182f0db x=100
     obj2 locate at AnObject@192d342 x=100

观察运行结果,显然obj2复制了obj1,因为这两个对象中存储的x值均为100,并且位于内存中不同的位置。

由上面的程序可知,要使得一个类的对象具有复制能力,必须显式地定义clone()方法,并且该类必须实现Cloneable接口。Cloneable接口中没有定义任何内容,只是起“标记”的作用,说明类的设计者已经为该类设计了复制的功能(这一点与第4章将要讲到的接口有所不同)。如果类没有实现Cloneable接口,则在运行时会抛出一个CloneNotSupportedException异常。