A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

如题,平时遇到的不多,这个接口没什么了解,只知道大概是克隆的意思。哪个同学详细说说他们的意义和使用。

5 个回复

倒序浏览

本帖最后由 钱兆元 于 2012-2-1 23:12 编辑

先给个JDK的解释:
1.此类实现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。   
2.  
3.如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常。   
4.  
5.按照惯例,实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。请参阅 Object.clone(),以获得有关重写此方法的详细信息。   
6.  
7.注意,此接口不 包含 clone 方法。因此,因为某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。   


我们平时需要对某个对象进行操作,但是这个对象被两个地方操作,却都要使用最原始时候的对象。这个时候就需要Cloneable接口出现了。并且如果我们对象里面的属性还有非基本类型对象的话也需要实现此接口直到没有属性是非基本类型对象为止。

clone的用法:

  1 声明实现Cloneable接口,这然使用如super.clone()方法时,会发生抛出cloneNotSupportedException。

  2 调用super.clone拿到一个对象,如果父类的clone实现没有问题的话,在该对象的内存存储中,所有父类定义的field都已经clone好了,该类中的primitive和不可变类型引用也克隆好了,可变类型引用都是浅copy。

  3 把浅copy的引用指向原型对象新的克隆体。

评分

参与人数 1技术分 +2 收起 理由
admin + 2

查看全部评分

回复 使用道具 举报
clone( )方法创建调用它的对象的一个复制副本。只有那些实现Cloneable接口的类能被复制。

Cloneable接口没有定义成员。它通常用于指明被创建的一个允许对对象进行位复制(也就是对象副本)的类。如果试图用一个不支持Cloneable接口的类调用clone( )方法,将引发一个CloneNotSupportedException异常。当一个副本被创建时,并没有调用被复制对象的构造函数。副本仅仅是原对象的一个简单精确的拷贝。

复制是一个具有潜在危险的操作,因为它可能引起不是你所期望的副作用。例如,假如被复制的对象包含了一个称为obRef的引用变量,当副本创建时,副本中的obRef如同原对象中的obRef一样引用相同的对象。如果副本改变了被obRef引用的对象的内容,那么对应的原对象也将被改变。这里是另一个例子。如果一个对象打开一个I/O流并被复制,两个对象将可操作相同的流。而且,如果其中一个对象关闭了流,而另一个对象仍试图对I/O流进行写操作的话,将导致错误。

由于复制可能引起问题,因此在Object内,clone( )方法被说明为protected。这就意味着它必须或者被由实现Cloneable的类所定义的方法调用,或者必须被那些类显式重载以便它是公共的。让我们看关于下面每一种方法的例子。

下面的程序实现Cloneable接口并定义cloneTest( )方法,该方法在Object中调用clone( )方法:

// Demonstrate the clone() method.



class TestClone implements Cloneable {

  int a;

  double b;



  // This method calls Object's clone().

  TestClone cloneTest() {

    try {

      // call clone in Object.

      return (TestClone) super.clone();

    } catch(CloneNotSupportedException e) {

      System.out.println("Cloning not allowed.");

      return this;

    }

  }

}



class CloneDemo {

  public static void main(String args[]) {

    TestClone x1 = new TestClone();

    TestClone x2;



    x1.a = 10;

    x1.b = 20.98;



    x2 = x1.cloneTest(); // clone x1



    System.out.println("x1: " + x1.a + " " + x1.b);

    System.out.println("x2: " + x2.a + " " + x2.b);

  }

}

这里,方法cloneTest( )在Object中调用clone( )方法并且返回结果。注意由clone( )方法返回的对象必须被强制转换成它的适当类型(TestClone)。

下面的例子重载clone( )方法以便它能被其类外的程序所调用。为了完成这项功能,它的存取说明符必须是public,如下所示:

// Override the clone() method.



class TestClone implements Cloneable {

  int a;

  double b;



  // clone() is now overridden and is public.

  public Object clone() {

    try {

      // call clone in Object.

      return super.clone();

    } catch(CloneNotSupportedException e) {

      System.out.println("Cloning not allowed.");

      return this;

    }

  }

}



class CloneDemo2 {

  public static void main(String args[]) {

    TestClone x1 = new TestClone();

    TestClone x2;



    x1.a = 10;

    x1.b = 20.98;



    // here, clone() is called directly.

    x2 = (TestClone) x1.clone();



    System.out.println("x1: " + x1.a + " " + x1.b);

    System.out.println("x2: " + x2.a + " " + x2.b);

  }

}

由复制带来的副作用最初一般是比较难发现的。通常很容易想到的是类在复制时是很安全的,而实际却不是这样。一般在没有一个必须的原因的情况下,对任何类都不应该执行Cloneable。

评分

参与人数 1技术分 +2 收起 理由
admin + 2

查看全部评分

回复 使用道具 举报
cloneable接口是一个标志性的接口,实现他可以不实现任何方法。使用了它就标志这个类可以复制,如果想实现深层次的克隆,那就要重载clone()方法。
若需要修改一个对象,同时不想改变调用者的对象,就用克隆,
先用implements Cloneble实现Cloneble接口,
再实现clone();

这是里面的一段(非完整的例子):
public class Snake implements Cloneable {

...........................

public Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {}
return o;

}


copy书上一段给你看看,希望有帮助把。。
当制作实例变量的一个引用时,原始实例变量和副本实力变量在内存中引用的均是同一个存储空间,这就意味着但对其中一个实例变量操作时就会影响到这个对象的副本。例如下面的程序代码。在执行时将会看到所画的两条线重合在一起,都是改变后的LineFigure1。
LineFigure lineFigure1 = new LineFigure();
LineFigure lineFigure2 = lineFigure1;
lineFigure1.draw(g);
…code for changing lineFigure1
lineFigure2.draw(g);
如果想让LineFigure2成为一个新的对象,就要用到Clone( )方法。Clone的后对象和原对象的存储空间不同,改变其中一个并不会对另一个产生任何影响。例如下面代码所示:
…………….
LineFigure2 = lineFigure1.clone();
…………….
如果LineFigure2中没有对其他对象的引用,事情就到此结束了,但LineFigure类中的实例变量StartPoint和EndPoint都是一个对象,即使简单地实现了对LineFigure1地Clone,可LineFigure1和LineFigure2的StartPoint和EndPoint实例变量引用的是同一个变量,要想完全的实现将LineFigure2和LineFigure1分离开,就要实现Cloneable接口,并重写Clone方法。Cloneable接口是Java提供的少数几个标签化接口之一。平常所说的标签化接口就是不提供任何方法的接口。在图形白板程序中,也用到了Cloneable接口,例如LineFigure类中的代码:
public class LineFigure extends Figure implements Cloneable{
public Object clone(){
LineFigure lineFigure = new LineFigure();
lineFigure.startPoint = (Point)startPoint.clone();
lineFigure.endPoint = (Point)endPoint.clone();
lineFigure.firstDraw = firstDraw;
return lineFigure;
}
………………..
}

评分

参与人数 1技术分 +2 收起 理由
admin + 2

查看全部评分

回复 使用道具 举报
当需要修改对象属性,又不想影响原来的属性值,这时候就应该使用clone了,前提是
该类必须实现Cloneable接口,实现接口是用来说明你的对象是允许复制的,如果不实现该接口
当调用clone()方法时,则会出现CloneNotSupportedException异常。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马