码迷,mamicode.com
首页 > 其他好文 > 详细

浅谈Cloneable的实现

时间:2015-03-28 23:04:18      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:

      今天看到原型法模式,就顺便先学了下Java的Cloneable接口,这个东西是个标记接口,里面什么都没有。我又找了Object中的clone方法,这个方法被声明为propected类型,但是在B类中new了一个A类的对象a,a却不能调用a.clone()方法。而在B类的对象b却可以调用clone方法b.clone();一开始没明白是怎么回事,后来一想A,B的父类虽然都是Object,但是毕竟是不同的父亲,ObjectA和A又不在一个包里面,而且它是A的父类,那么当然只能在ObjectA的子类A中使用子类没有重写的方法。

         接着往下走,虽然Object中有clone()方法,但是直接在A类中使用此方法会出现CloneNotSupportedException错误。直接看API,它大体意思是这样的:Object中的clone()方法是实现特定的复制操作,比如数组(因为数组均已经模式实现了这个接口),其它的类如果想要调用clone()方法就需要实现Cloneable接口。

         最后再说一下浅复制和深复制,在Java中,可以这么理解,浅复制就是复制了一份引用,而深复制就是复制了引用指代的对象,显然,我们所要的clone()方法要达到深复制的效果,因为复制引用显然是没必要费这么大劲的。

         首先我们来看看浅复制,在这里我们有三个类,一个测试类Test,一个类A,一个Index类。具体代码如下:

         A类中有一个String类型的name属性,外加一个Index对象类型的属性。

public class A implements Cloneable{
    String name;
    Index b;
    public int getIndex() {
        return b.getIndex();
    }
    public Index index(){
        return b;
    }
    public void setIndex(Index b) {
        this.b = b;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public A clone() throws CloneNotSupportedException{
        return (A) super.clone();
    }
}

          Index类中有设置索引大小的方法和属性

public class Index {
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }
    int index;
}

         测试类:

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {
        A a = new A();
        a.setName("A");
        Index index = new Index();
        index.setIndex(0);
        a.setIndex(index);
        System.out.println(a.getName());//A
        System.out.println(a.getIndex());//0
        System.out.println("复制了一份a");
        A b = a.clone();
        System.out.println("修改b之前的属性");
        System.out.println(b.getName());//A
        System.out.println(b.getIndex());//0
        b.setName("B");
        index.setIndex(999);
        b.setIndex(index);
        System.out.println("修改b之后的属性");
        System.out.println(b.getName());//B
        System.out.println(b.getIndex());//999
        System.out.println("修改完b之后查看a对象中的属性");
        System.out.println(a.getName());//A
        System.out.println(a.getIndex());//999
        
        System.out.println(b.index().equals(a.index()));//true
    }
}

       上面就是浅复制,在复制的时候并木有完全将对象内容复制一遍,对象中的引用类型的属性只是复制了引用而已。

       改成深复制为:则在Index中同样要实现Cloneable接口,且在A类的clone()方法中添加:

public A clone() throws CloneNotSupportedException{
        b = b.clone();
        return (A) super.clone();
    }
    //同样的Test类测试结果为:
A
0
复制了一份a
修改b之前的属性
A
0
修改b之后的属性
B
999
修改完b之后查看a对象中的属性
A
0
False

         所以,如果我们所要克隆复制的对象中有引用对象存在的时候,一定要注意深复制的问题。

 

浅谈Cloneable的实现

标签:

原文地址:http://www.cnblogs.com/zhangxd-stn/p/roomy_java_0.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!