`

java中clone的学习

阅读更多
今天看了下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这个方法有很多问题的,所以很多大牛们都是不推荐用的,基本的问题留给以后慢慢发掘了~~~
3
4
分享到:
评论
2 楼 小草一棵 2012-09-06  
lihengzkj 写道
其实关于克隆map空的解决办法不是最好的,就好像你克隆了一个对象,然后再来克隆对象中的对象。在 java中克隆可以分为浅度克隆和深度克隆,深度克隆就能一次性把对象和对象中的对象,或者还有更深次的对象一起克隆出来,你可以关注一下。

嗯谢谢指点
1 楼 lihengzkj 2012-09-05  
其实关于克隆map空的解决办法不是最好的,就好像你克隆了一个对象,然后再来克隆对象中的对象。在 java中克隆可以分为浅度克隆和深度克隆,深度克隆就能一次性把对象和对象中的对象,或者还有更深次的对象一起克隆出来,你可以关注一下。

相关推荐

    clone()示例源码

    在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在处理对象复制和克隆时。...通过阅读描述中的博客文章,读者可以期待学习到如何有效地利用`clone()`,以及何时应该考虑其他复制策略。

    JAVA对象clone方法代码实例解析

    JAVA对象clone方法代码实例解析 JAVA对象clone方法是JAVA编程语言...最后,我们可以看到,JAVA语言提供了一个 Cloneable接口和clone方法来实现对象的复制,但是,它们的实现细节被隐藏了起来,留给我们去探索和学习。

    CoreJava学习笔记

    ### CoreJava学习笔记 #### 一、JAVA特点与运行原理 **JAVA特点:** 1. **简单性**:Java的设计者们将C++语言中许多不易理解和容易混淆的部分去除,使得Java更容易理解与掌握。 2. **面向对象**:Java几乎一切都...

    Java设计模式学习.pdf

    文档中描述的是Java设计模式学习笔记,目前涉及了7种设计模式,但没有具体指明这7种模式是什么,计划后续增加更多的模式。虽然文件内容中存在OCR扫描的识别错误,但不影响我们从整体上把握设计模式的脉络和学习方法...

    Java基础学习15.pdf

    4. Java中的常见API使用,例如Object类的equals、toString、clone、finalize、hashcode、getClass、notify、notifyAll、wait等方法的使用。这些方法都是在Java面向对象编程中常用的。 5. 大数值运算,提到了...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    Java编程老鸟潜心写作,奉献高效率的Java学习心得 完全站在没有编程经验读者的角度,手把手教会读者学习Java 配16小时多媒体教学视频,高效、直观 一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让...

    clone()方法示例(对象克隆)_对象克隆_nervouse78_源码

    在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在处理对象复制和数据持久化时。...通过`nervouse78`的示例,你可以学习到如何在实际项目中运用`clone()`,从而提高代码的复用性和灵活性。

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    Java编程老鸟潜心写作,奉献高效率的Java学习心得 完全站在没有编程经验读者的角度,手把手教会读者学习Java 配16小时多媒体教学视频,高效、直观 一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让...

    java的设计模式 《设计模式-java语言中的应用.pdf》

    设计模式是软件工程中的一种最佳实践,它是在特定上下文中解决常见问题的模板或蓝图。...通过阅读《设计模式——Java语言中的应用》这本书,你可以更深入地学习和掌握这些模式的细节及其在实际开发中的应用。

    clone

    这种操作常见于对象导向编程,例如在Java、Python、C#等语言中。通过克隆,我们可以创建一个原始对象的独立副本,对副本进行修改不会影响原始对象,这在数据处理和并发编程中尤其有用。 2. **深度克隆与浅克隆** -...

    JAVA版数据结构.pdf

    文档中提到了在`clone()`方法中的异常处理,这表明文档可能涉及Java中的异常处理机制,包括`try`、`catch`、`finally`和`throw`关键字的使用。 11. Java类的继承和接口 文档提到了`implements`关键字,这涉及到Java...

    初级java笔试题-clone:克隆

    初级java笔试题编程面试大学 我最初创建它是为了成为一名软件工程师的学习主题的简短待办事项列表,但它增长到您今天看到的大列表。 完成这个学习计划后,! 你可能不需要像我一样学习。 总之,你需要的都在这里。 ...

    Java和Android开发学习指南源码(第二版)

    《Java和Android开发...通过研究`budi-kurniawan-java4android2-examples-1d5a9b6ffc21`这个压缩包中的源码,开发者不仅可以学习到理论知识,还能获得实际编码的实践经验,这对于提升Java和Android开发技能大有裨益。

    【Java面试+Java后端技术学习指南】

    【Java面试+Java后端技术学习指南】 在Java领域,面试和实际开发是相辅相成的两个重要环节。为了成为一名出色的Java后端开发者,掌握扎实的理论基础、丰富的实战经验以及良好的问题解决能力至关重要。以下是一些...

    Java面试指南.pdf

    Java面试的准备可以分为几个部分,其中最重要的部分是Java技术相关,包括了Java的基础知识、核心API的解读以及Java中高级技术的理解。同时,面试者应该熟悉应聘流程,了解如何撰写简历,以及在面试中如何谈论福利...

    java 学习心得可以帮助大家

    例如,在给定的部分内容中提到了`Object`类,这是所有Java类的根类,提供了诸如`clone()`、`equals()`等通用方法。 #### 2. 方法(Method)与字段(Field) 在Java中,类由方法和字段组成。方法定义了类的行为,而字段...

    darts-clone-java-master.zip_DARTS代码_darts

    在本压缩包"Darts-Clone-Java-Master.zip"中,包含了Java实现的DARTS算法源代码,非常适合初学者深入理解和实践时间序列分析。 DARTS的核心思想是通过自回归模型(AR,AutoRegressive)来预测未来的值,其中每个...

    Java 调用 SAP RFC 案例

    在IT领域,尤其是在企业系统集成中,Java与SAP系统的交互是常见的需求。SAP RFC(Remote Function Call)提供了一种标准方式,使得外部应用程序能够调用SAP系统中的功能模块。本篇将深入探讨如何在Java环境中实现对...

Global site tag (gtag.js) - Google Analytics