克隆对象

  • clone()方法是Object类的方法,是protected类型,同时也是native方法。
  • 默认的克隆操作是“浅拷贝”,只能对对象逐个域进行拷贝,并没有克隆对象中引用的其他对象(对于子对象采用共享的方式),一般只是克隆基本数据类型
  • 浅拷贝有什么影响?
    • 如果原对象与浅克隆对象共享的子对象是不变的,那么这种共享就是安全的。如果子对象属于不可变的类,如String;或者子对象一直包含不变的常量,没有更改器方法会改变它,也没有方法生成它的引用,这种情况下是安全的。
  • 通常子对象都是可变的,必须重新定义clone方法来建立“深拷贝”,同时克隆所有的子对象
  • 对于每一个类,需要确定:
    • 默认的clone()方法是否满足要求。
    • 是否可以在可变的子对象上调用clone方法来修补默认的clone方法。
    • 是否不该使用clone。
  • 如果对象要调用clone方法,所属类必须:
    • 实现Cloneable接口
    • 重新定义clone方法,并指定修饰符为public。
  • Cloneable接口中没有clone方法,该方法是从Object类中继承的。如果一个对象请求克隆,但是没有实现该接口,会出现异常。Cloneable接口是Java提供的标记接口(tagging interface)。标记接口不包含任何方法,唯一的作用就是在类型查询中使用instanceOf。
  • 即使clone的默认(浅拷贝)能够满足要求,还是需要实现Cloneable接口,将clone()方法定义为public ,再调用super.clone()
    //默认的clone方法返回类型为Object
     public CloneTest clone() throws CloneNotSupportedException{
         return (CloneTest)super.clone();
    }
  • 要实现深拷贝,还要克隆对象中可变的实例域。
     public CloneTest clone() throws CloneNotSupportedException{
         CloneTest cTest=(CloneTest)super.clone();
          cTest.day=(Date)day.clone();
         return cTest;
    }
  • 如上,还要对CloneTest类中的Date day变量进行克隆,由于Date类已经实现了Cloneable接口,所以可以调用clone方法对子对象进行克隆。
  • 所有的数组类型都有一个public的clone方法,可以用这个方法建立一个新数组,包含原数组的所有副本元素。
package Clone;

public class CloneArray {

    public static void main(String[] args) {
         // TODO Auto-generated method stub
         int[] original={0,1,2,3,4,5,6,7,8,9};
         int[] cloned=null;
         cloned=original.clone();
         System.out.println("原数组元素:");
         for (int i = 0; i < original.length; i++) {
             System.out.print(original[i]);
         }
         System.out.println("\n克隆数组元素:");
         for (int i = 0; i < cloned.length; i++) {
             System.out.print(cloned[i]);
         }
         for (int i = 0; i < cloned.length; i++) {
             cloned[i]=10-i;
         }
         System.out.println("\n原数组元素:");
         for (int i = 0; i < original.length; i++) {
             System.out.print(original[i]);
         }
         System.out.println("\n克隆数组元素:");
         for (int i = 0; i < cloned.length; i++) {
             System.out.print(cloned[i]);
         }
    }

}
  • 输出如下:
原数组元素:
0123456789
克隆数组元素:
0123456789
原数组元素:
0123456789
克隆数组元素:
10987654321
  • 浅拷贝实例:
package Clone;

public class CloneTest implements Cloneable {
    private int a=10;
    private double b=2.0;
    public void setA(int a){
         this.a=a;
    }
    public int getA(){
         return this.a;
    }
    public void setB(double b){
         this.b=b;
    }
    public double getB(){
         return this.b;
    }
    public CloneTest clone() throws CloneNotSupportedException{
         return (CloneTest)super.clone();
    }
    public static void main(String[] args) {
         CloneTest cloneTest=new CloneTest();
         CloneTest cloneTest2 = null;
         try {
             cloneTest2=cloneTest.clone();
         } catch (CloneNotSupportedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
        System.out.println("Clonetest.a="+cloneTest.getA()+"   Clonetest.b="+cloneTest.getB());
        System.out.println("Clonetest2.a="+cloneTest2.getA()+"   Clonetest2.b="+cloneTest2.getB());
         cloneTest2.setA(3);cloneTest2.setB(3.0);
        System.out.println("Clonetest.a="+cloneTest.getA()+"   Clonetest.b="+cloneTest.getB());
        System.out.println("Clonetest2.a="+cloneTest2.getA()+"   Clonetest2.b="+cloneTest2.getB());
    }

}


















































































































  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值