java中clone的学习_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > java中clone的学习

java中clone的学习

 2012/9/8 11:52:13  小草一棵  程序员俱乐部  我要评论(0)
  • 摘要:今天看了下effectivejava中的clone的使用,对其有了一点了解,下面就把自己理解的写下来,以便以后运用~~~~java中要实现对象的拷贝,就可以用Object的clone()方法,对于自己的写的类要实现cloneable接口,并且覆盖父类的clone()方法。传统的对象赋值如:publicclassTest{privateStringstr;publicTest(Stringstr){this.str=str;}publicvoidsetStr(Stringstr){this
  • 标签:学习 Java
今天看了下effective java 中的clone的使用,对其有了一点了解,下面就把自己理解的写下来,以便以后运用~~~~
java中要实现对象的拷贝,就可以用Object的clone()方法,对于自己的写的类要实现cloneable接口,并且覆盖父类的clone()方法。
传统的对象赋值如:
public class Test{
    private String str;
    public Test(String str){
        this.str = str;
    }
    public void setStr(String str){
        this.str = str;
    }
    public String getStr(){
        return this.str;
    }
    public static void main(String args[]){
        Test t1 = new Test("www");
        Test t2 = t1;
        t2.setStr("ddd");
        System.out.println(t1.getStr());//输出ddd
        System.out.println(t2.getStr());//输出ddd
    }
}

上面 t2 = t1只是把让t1和t2同时指向了同一块内存,对于t2的改变也会影响到t1,那如果我想要t2的改变不影响t1应该怎么办呢?
其实很简单,这就可以用到Object类的clone()方法,同时实现Cloneable接口改进后的代码,如下:
public class Test implements Cloneable{
    private String str;
    public Test(String str){
        this.str = str;
    }
    public void setStr(String str){
        this.str = str;
    }
    public String getStr(){
        return this.str;
    }
    public static void main(String args[]) throws CloneNotSupportedException{
        Test t1 = new Test("www");
        Test t2 = (Test) t1.clone();
        t2.setStr("ddd");
        System.out.println(t1.getStr());//输出www
        System.out.println(t2.getStr());//输出ddd
    }
}

这样t2是一个新的对象引用,就类似于Test t2 = new Test("www"),t1和t2 指向不同的内存空间,对t2设置 值不会影响到t1。
但是这样做又会产生另一个问题,看下面的代码:
public class Test implements Cloneable{
    private String str;
    private HashMap<Integer, String> map = new HashMap<Integer, String>();
    public Test(String str){
        this.str = str;
        map.put(1, "1111");
        map.put(2, "2222");
        map.put(3, "3333");
    }
    public void setStr(String str){
        this.str = str;
    }
    public String getStr(){
        return this.str;
    }
    public HashMap<Integer, String> getMap(){
    	return this.map;
    }
    public static void main(String args[]) throws CloneNotSupportedException{
        Test t1 = new Test("www");
        Test t2 = (Test) t1.clone();
        t2.setStr("ddd");
        System.out.println(t1.getStr());//输出www
        System.out.println(t2.getStr());//输出ddd
        
        t2.getMap().put(4, "4444");
        System.out.println(t1.getMap().get(4));//输出4444(我们设想的值应该是null)
        System.out.println(t2.getMap().get(4));//输出4444
    }
}

可以看到上面的t1中的输出并不是null,而是4444,这是为什么呢???
其实Object类中的clone()方法,可以简单的理解为复制一个内部元素值相同的对象出来,如上面的程序,t1和t2中的map成员变量所指向的内存地址是一样的,所以你可以任意其中一个改变map的值,这样他们就不指向同一内存空间,但是你如果去修改map中的键值的话,他们两个是同时指向同一个空间的,一个改变,另一个也会改变。
解决方法如下:
public class Test implements Cloneable{
    private String str;
    private HashMap<Integer, String> map = new HashMap<Integer, String>();
    public Test(String str){
        this.str = str;
        map.put(1, "1111");
        map.put(2, "2222");
        map.put(3, "3333");
    }
    public void setStr(String str){
        this.str = str;
    }
    public String getStr(){
        return this.str;
    }
    public HashMap<Integer, String> getMap(){
    	return this.map;
    }
    
    public static void main(String args[]) throws CloneNotSupportedException{
        Test t1 = new Test("www");
        Test t2 = (Test) t1.clone();
        t2.setStr("ddd");
        
        System.out.println(t1.getStr());//输出www
        System.out.println(t2.getStr());//输出ddd
        
        t2.getMap().put(4, "4444");
        System.out.println(t1.getMap().get(4));//输出null
        System.out.println(t2.getMap().get(4));//输出4444
    }
    
    @Override public Test clone(){
    	Test obj = null;
    	try {
    		obj = (Test) super.clone();
    		obj.map = (HashMap<Integer, String>) obj.map.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return obj;
    }
}

重写clone()方法并且把成员变量也clone()一份,这样就可以解决上面的问题,对象数组也是这样处理的,事实上只要你用的对象的clone()方法,最好都重写clone()方法
    @Override public Test clone(){
    	Test obj = null;
    	try {
    		obj = (Test) super.clone();
                //clone其他类成员对象
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return obj;
    }

哎,总算写完了,JDK中的clone这个方法有很多问题的,所以很多大牛们都是不推荐用的,基本的问题留给以后慢慢发掘了~~~
发表评论
用户名: 匿名