Cloneable Interface in java

Cloneable Interface in java

发表于1年前(2014-04-24 01:37)   阅读( 38) | 评论( 0)  2人收藏此文章, 我要收藏
0

 一个类实现该接口表明该类的实例通过java.lang.Object#clone()方法拷贝字段的字段是合法的。
 在一个没有实现该接口的实例上调用对象的clone方法会抛出CloneNotSupportedException异常。
 通常,类实现该接口应该用public重写Object.clone方法(protected)。
 注意,该接口没包含clone方法,因此,仅仅实现该接口是不可能克隆对象,即使通过反射调用克隆方法,也不能保证它会成功。
 
 克隆一个对象是一个对象的不同标识和相同的内容,定义克隆,一个类必须实现Cloneable接口并且使用public重写对象的clone方法。此时,
 克隆接口没有包含任何克隆方法,对象的clone方法是protected。
 
//没有实现该接口的实例上调用对象的clone方法会抛出CloneNotSupportedException异常

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public  class  Person {
  private  String name;
  
  public  Person(String name) {
   this .name = name;
  }
  
  public  String getName() {
   return  name;
  }
  
  public  static  void  main(String[] args) {
   Person p =  new  Person( "Sam" );
   try  {
    Person pClone = (Person)p.clone();
    System.out.println(pClone.getName());
   catch  (CloneNotSupportedException e) {
    e.printStackTrace();
   }
  }    
  
}

//如果类想允许客户端克隆它的实例,必须使用public修饰符重写对象的clone方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public  class  Person  implements  Cloneable {
  private  String name;
  
  public  Person(String name) {
   this .name = name;
  }
  
  public  String getName() {
   return  name;
  }
  
  @Override
  public  Person clone() {
   try  {
    return  (Person) super .clone();
   catch  (CloneNotSupportedException e) {
    e.printStackTrace();
    throw  new  RuntimeException();
   }
  }
  
  public  static  void  main(String[] args) {
   Person p =  new  Person( "Sam" );
   Person pClone = p.clone();  //如果clone不是public,不能调用
   System.out.println(pClone.getName());
  }    
  
}

怎样实现clone方法?
如果在一个non-final类中重写clone方法,你应该通过调用super.clone返回一个对象。
如果所有类的父类都服从这个规则,则调用super.clone将最终调用Object.clone方法,创建一个正确类的实例。

//若下面的类没有服从该规则

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public  class  Animal  implements  Cloneable {
  private  String name;
  
  public  Animal(String name) {
   this .name = name;
  }
  
  public  String getName() {
   return  name;
  }
  
  public  String bark() {
   return  "This is how i bark, better care not" ;
  }
  
  public  Animal clone() {
   //当创建正确类的实例违法了调用super.clone()
   return  new  Animal(name);
  }
  
}
public  class  Dog  extends  Animal {
  public  Dog(String name) {
   super (name);
  }
  
  public  String bark() {
         return  "Bow Bow!!" ;
     }
  
  public  Dog clone() {
   return  (Dog) super .clone();
  }
}
public  class  CloneableTest {
  public  static  void  main(String[] args) {
   Dog dog =  new  Dog( "Puppy" );
   Dog dogClone = dog.clone(); //无法转换类型
   System.out.println(dogClone.getName());
  }
}
  
Exception in thread  "main"  java.lang.ClassCastException: Animal cannot be cast to Dog
  at Dog.clone(Dog.java: 13 )
  at CloneableTest.main(CloneableTest.java: 6 )

一旦从super.clone()中获得了对象,需要根据类的性质可能做一些修改
如果每个字段包含一个原始类型的值or引用一个不可变对象,不需要进一步处理。
如果引用了可变对象,为了克隆工作正常,它要求调用这些可变引用的clone方法。

//克隆可变引用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public  class  Person  implements  Cloneable {
  private  String name;
  private  Date dob;
  
  public  Person(String name, Date dob) {
   this .name = name;
   this .dob = dob;
  }
  
  public  String getName() {
   return  name;
  }
  
  public  Date getDob() {
   return  dob;
  }
  
  @Override
  public  Person clone() {
   Person p;
   try  {
    p = (Person) super .clone();
    p.dob = (Date) dob.clone();
    return  p;
   catch  (CloneNotSupportedException e) {
    e.printStackTrace();
    throw  new  RuntimeException();
   }
  }
  
  public  static  void  main(String[] args) {
   Person p =  new  Person( "Sam" new  Date());
   Person pClone = p.clone();
   System.out.println(pClone.getName());
   System.out.println(pClone.getDob());
   System.out.println(pClone.getDob() == p.getDob());
  }    
  
}

若有final字段指向可变的对象,为了是一个类可克隆,可能需要从一些字段中移除final修饰符(deep clone)。
如果实现一个线程安全可克隆类,注意它的clone方法必须正确同步就像任何其他方法一样。
实现clone方法非常棘手,避免实现它,寻找其他可代替方法


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值