`
dcriori
  • 浏览: 97151 次
社区版块
存档分类
最新评论

关于java中克隆的学习(二)

阅读更多

第一部分说了传值的问题,今天接着来看clone的问题。

package dcr.study.test.clone;

import java.util.Date;

/*
 * 在实际编程中我们会遇到一种问题,比如,我们有一个客户,他每次来订货,订单上的商品几乎都是一样的
 * 这时每次去录入商品,显然很烦,这个时候,我要参照以往的单据去创建一张新的订单。然后做些细微的修
 * 改,这样就不用每次去录这个客户的信息和商品。
 * 
 * 这种情况,用简单的赋值语句,不太好。有很多方法去实现这个需求,但用clone应该是一个比较好的方式。
 * 
 * 
 *  这里值得注意的是Obj必须实现Cloneable接口,否则在使用clone方法的时候,会报
	java.lang.CloneNotSupportedException异常
	这里我们发现Cloneable接口是一个抽象接口,是不包含任何方法的
	public abstract interface java.lang.Cloneable {}
	其实这个接口仅仅是一个标志,而且这个标志也仅仅是针对Object类中clone()方法的,
	如果clone类没有实现Cloneable接口,并调用了Object的clone()方法
	(也就是调用了super.Clone()方法),那么Object的clone()方法就会抛出 
	CloneNotSupportedException异常。 
 * */
public class OrderClone implements Cloneable{
	private String buyer;
	private Date date;
	private int number;
	public String getBuyer() {
		return buyer;
	}
	public void setBuyer(String buyer) {
		this.buyer = buyer;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}
	public int getNumber() {
		return number;
	}
	public void setNumber(int number) {
		this.number = number;
	}
	
	public Object clone(){
		OrderClone o = null;
		try {
			o = (OrderClone)super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return o;
	}
}
 
package dcr.study.test.clone;
/*
 * 没有实现克隆接口
 * */
public class UnCloneA {
	private int i;

	public UnCloneA(int ii) {
		i = ii;
	}

	public void doublevalue() {
		i *= 2;
	}

	public String toString() {
		return Integer.toString(i);
	}
}
 

 

package dcr.study.test.clone;

public class CloneB implements Cloneable {
	public int aInt;
	public UnCloneA unCA = new UnCloneA(123);

	public Object clone() {
		CloneB o = null;
		try {
			o = (CloneB) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return o;
	}
}

 

package dcr.study.test.clone;

import java.sql.Date;
/*总结:
   Clone()方法的使用比较简单,注意如下几点即可:
a. 什么时候使用shallow Clone,什么时候使用deep Clone,这个主要看具体对象的域是什么性质的,
    基本型别还是reference variable
b. 调用Clone()方法的对象所属的类(Class)必须implements Clonable接口,否则在调用Clone方法的
    时候会抛出CloneNotSupportedException。如果仔细看你会发现Cloneable接口只是个抽象接口
    并没有任何方法,他只是个标记。 
 * */
public class OrderTest {
	
	public static void main(String[] args) {
		OrderClone o1= new OrderClone();
		o1.setBuyer("dcriori");
		o1.setDate(new Date(0));
		o1.setNumber(10000);
		
		OrderClone o2 = o1;
		OrderClone o3 = (OrderClone) o1.clone();
		
		o2.setBuyer("sagaris");
		o2.setNumber(20000);
		
		System.out.println("O1  \nBuyer:"+o1.getBuyer()+"\nDate:" 
				+ o1.getDate() + "\nNumber:" + o1.getNumber());
		System.out.println("O2  \nBuyer:"+o2.getBuyer()+"\nDate:" 
				+ o2.getDate() + "\nNumber:" + o2.getNumber());
		System.out.println("O3  \nBuyer:"+o3.getBuyer()+"\nDate:" 
				+ o3.getDate() + "\nNumber:" + o3.getNumber());
		/*
		 * 运行结果:
		 *  O1  
			Buyer:sagaris
			Date:1970-01-01
			Number:20000
			O2  
			Buyer:sagaris
			Date:1970-01-01
			Number:20000
			O3  
			Buyer:dcriori
			Date:1970-01-01
			Number:10000
			
			通过运行结果我们发现 OrderClone o2 = o1;o2是通过赋值创建的对象,o2在改变的时候,把o1也改
			掉了,这不是我们想要的结果。但o3没有变,说明用clone创建出来的对象,和原来的对象没指向同一块
			内存。
			
		 * */
		System.out.println("============================================");
		System.out.println("=============下面是影子克隆的情况===============");
		System.out.println("============================================");
		
		CloneB b1 = new CloneB();
		b1.aInt = 11;
		System.out.println("before clone,b1.aInt = "+ b1.aInt);
		System.out.println("before clone,b1.unCA = "+ b1.unCA);

		CloneB b2 = (CloneB)b1.clone();
		b2.aInt = 22;
		b2.unCA.doublevalue();
		System.out.println("=================================");
		System.out.println("after clone,b1.aInt = "+ b1.aInt);
		System.out.println("after clone,b1.unCA = "+ b1.unCA);
		System.out.println("=================================");
		System.out.println("after clone,b2.aInt = "+ b2.aInt);
		System.out.println("after clone,b2.unCA = "+ b2.unCA); 
		/*    ============================================
			=============下面是影子克隆的情况===============
			============================================
			before clone,b1.aInt = 11
			before clone,b1.unCA = 123
			=================================
			after clone,b1.aInt = 11
			after clone,b1.unCA = 246
			=================================
			after clone,b2.aInt = 22
			after clone,b2.unCA = 246
 		 * 这里我们发现,类CloneB虽然实现了Cloneable接口,也写了Clone方法,但是由于使用了其它未
		 * 实现Cloneable接口的类UnCloneA因此在改变b2的unCA的值的时候,把b1的unCA的值也改掉了
		 * 这说明在clone的时候,对于基础类型没有什么问题,但是对于类类型,问题就来了,我们知道它们
		 * 保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。
		 * 
		 * 解决这个问题的办法,就是深度clone,
		 * 其实说起来也很简单,两个方法,
		 * 一是把UnCloneA类也实现Cloneable接口,重载clone()方法;
		 * 二是在CloneB的clone()方法中加入一句o.unCA = (UnCloneA)unCA.clone();
		 * 代码就不再写了。
		 * */
	}

}

 

 

分享到:
评论

相关推荐

    java代码-使用java解决克隆问题的源代码

    java代码-使用java解决克隆问题的源代码 ——学习参考资料:仅用于个人学习使用!

    Java学习网站大全

    "Java学习网站大全"这个资源集合就是为了满足这样的需求,它为你提供了丰富的学习平台和工具,帮助你在Java的世界里稳步前行。 1. **学习资源** - **Oracle官方文档**:Java的官方教程,涵盖了从基础到高级的所有...

    JAVA常用API文档 中文完整版.zip

    在Java API文档中,我们可以找到关于Java语言的基本类、集合框架、网络编程、多线程、I/O流、反射、异常处理、国际化、日期时间、XML处理等多个领域的详细说明。以下是一些关键知识点的概述: 1. **基础类与接口**...

    java课程学习.zip

    这个zip文件包含了一个名为"java-course-learning-java-master"的项目目录,预示着它可能是一个GitHub仓库的克隆,里面可能包含了各种代码示例、练习和项目文件,帮助学习者深入理解Java编程。 Java是一种广泛使用...

    java2python--java代码转python工具

    Java到Python的转换工具,如标题“java2python”所示,是编程领域中的一种实用技术,旨在帮助开发者将已有的Java代码转换为Python语言。这种转换对于那些熟悉Java但希望进入Python生态系统,或者想要利用Python特定...

    Java入门到精通完整教程+源码.zip

    Java编程语言是软件开发领域广泛使用的工具,尤其在企业级应用和互联网开发中占据着重要地位。本资源“Java入门到精通完整教程+源码.zip”提供了一个全面的学习路径,帮助初学者逐步掌握Java编程技能并进阶至精通。...

    Java 的常用包与数组的复制与排序25

    在Java编程语言中,"Java的常用包"和"数组的复制与排序"是学习的基础且重要的部分。这里,我们主要探讨的是Java的核心库包以及如何处理数组,特别是复制和排序的操作。 首先,让我们深入了解Java的常用包。Java标准...

    java ee练习代码,基础语法+高级特性 Java学习资料

    在“it_cast-master”这个文件名中,我们可以推测这可能是一个开源项目或者学习资源的仓库,可能是从Git平台如GitHub上克隆下来的。"it_cast"可能是一个组织或个人的标识,而"master"通常是Git仓库的主分支,包含了...

    最新整理的JAVA学习资料

    5. **异常处理**:Java中的异常处理机制可以帮助开发者编写健壮的程序,学习如何使用try-catch-finally语句以及不同类型的异常是必要的。 6. **JavaFX和Swing**:这两个是Java的图形用户界面(GUI)工具包,对于...

    Java面试指南.pdf

    除此之外,本指南还涉及到了Collection与Collections的区别、IO与NIO的区别、Java中如何实现浅克隆与深克隆以及枚举类型是否可以序列化等问题。每个知识点的解释都不会过于深入,而是倾向于提供快速复习的要点,帮助...

    java 学习入门 ppt

    这份“java学习入门ppt”提供了一个理想的起点,帮助初学者掌握Java的基础知识,并了解如何与数据库进行交互。以下是对这份资源中可能包含的关键知识点的详细说明: 1. **Java基础**: - **语法特性**:Java语言的...

    java-study是本人学习Java过程中记录的一些代码!从Java基础的数据类型、jdk1.8的Lambda、Stream和日期的使用、IO流、数据集合、多线程使用、ARM编程、23种设计.zip

    Java 学习介绍java-study是本人学习Java过程中记录的一些代码!从Java基础的数据类型、jdk1.8的使用、IO、集合、线程等等技术以及一些常用框架,netty、mina、springboot、kafka、storm、 Zookeeper、es、redis、...

    MAC下java调用opencv包含opencv_454.jar和libopencv_java454.dylib

    在Mac环境下,使用Java调用OpenCV库是一个常见的需求,特别是在计算机视觉和图像处理的项目中。OpenCV是一个强大的开源库,提供了丰富的功能,用于图像处理、计算机视觉算法以及机器学习。本文将详细介绍如何在Mac上...

    Thinking in Java 中文第四版+习题答案

    2. Java的学习 3. 目标 4. 联机文档 5. 章节 6. 练习 7. 多媒体 8. 源代码 9. 编码样式 10. Java版本 11. 课程和培训 12. 错误 13. 封面设计 14. 致谢 第1章 对象入门 1.1 抽象的进步 1.2 对象的接口 1.3 实现方案的...

    设计模式java 版本

    Java提供了`java.lang.Cloneable`接口来实现对象的克隆。 5. **适配器模式**:将一个类的接口转换成客户希望的另一个接口。适配器使原本不兼容的类可以一起工作。在Java中,这通常通过继承或组合来实现。 6. **...

    java设计模式pdf

    通过克隆机制实现了原型模式,并探讨了其在Java中的实现细节。 #### 五、Java基础类库 在第二章(第52页),作者详细介绍了Java基础类库(JFC)的安装和使用方法,并深入探讨了Swing组件的设计理念及其类层次结构...

    java控制默认输出音频和控制屏幕克隆

    内容概要:控制windows系统的其它屏幕克隆其中一个屏幕内容,控制系统...能学到什么:有助于你学习用java怎么调用win的SDK方式 阅读建议:此资源用java调用c++封装好的dll,附带dll了,有需求的用户可以下载尝试下。

    Java设计模式入门闲谈

    在Java中,实现原型模式通常涉及`java.lang.Cloneable`接口以及重写`Object`类中的`clone()`方法。`Cloneable`接口是一个标记接口,表明一个类可以被克隆。而`clone()`方法则负责执行实际的克隆操作。值得注意的是,...

Global site tag (gtag.js) - Google Analytics