首先,区分一下拷贝和克隆:

拷贝:当拷贝一个变量时,原始变量与拷贝变量引用的是同一个对象。当改变一个变量所引用的对象,则会对另一个变量造成影响。

克隆:当克隆一个对象时,是重新的创建了和该对象内容相同的对象。

clone方法是Object类受保护(preteced)方法,用户编写的代码不能直接调用。只有相同的类才能克隆其本身。

问题:

如果待克隆的对象中的所有数据域都是数值或基本类型,这样的克隆没有问题。

但是,如果在对象中包含了子对象的引用,拷贝的结果就会使得两个域引用同一个子对象,此时,原始对象和克隆对象将共享这一部分信息。

这样,当克隆对象改变这部分时,就会造成原始对象中数据的改变。

默认的克隆操作都是浅拷贝,它并没有克隆包含在对象中的内部对象。

进行浅拷贝会发生什么?

如果原始对象与浅克隆对象共享的子对象是不可变的,这样就不会产生问题。

但是,更多的情况是子对象是可变的。这样,就必须重写clone方法,以实现克隆子对象的深度拷贝。

对于待克隆的对象,需要作出一些判断:

(1)默认的克隆方法是否能够满足要求;

(2)默认的克隆方法是能够通过调用可变子对象的clone方法进行修补;

(3)是否不应该使用clone。

如果选1或2,类必须:

实现Cloneable接口,并使用public访问修饰符重新定义clone方法。

下面举例说明克隆机制:

import java.util.Date;
import java.util.GregorianCalendar;

public class TestClone {
	public static void main(String[] args) {
		try {
			/**原始对象**/
			Employee origin = new Employee("Tom", 10000);
			origin.setHireDay(2014, 10, 10);
			/**克隆Employee对象**/
			Employee copy = origin.clone();
			copy.raiseSalary(10);
			copy.setHireDay(2015, 11, 11);
			System.err.println(origin); /**Tom,10000.0,Mon Nov 10 00:00:00 CST 2014**/
			System.err.println(copy);   /**Tom,11000.0,Fri Dec 11 00:00:00 CST 2015**/
			/**
			 * 可以看出数据域属于数值或基本类型时,克隆不会对其值造成影响,
			 * 而类似Date这样的对象在进行克隆时就需要特别注意,必须进行深度克隆,将子对象也进行克隆
			 */
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}
}

class Employee implements Cloneable {
	private String name;
	private double salary;
	private Date hireDay;

	public Employee(String n, double s) {
		this.name = n;
		this.salary = s;
		this.hireDay = new Date();
	}

	public Employee clone() throws CloneNotSupportedException {
		/** 调用Object的clone方法 **/
		Employee cloned = (Employee) super.clone();

		/** 克隆可变的域对象 对可变的子对象进行克隆 **/
		cloned.hireDay = (Date) hireDay.clone();

		/**如果注释掉上面hireDay的克隆,最终将会得到如下结果,原始对象和克隆对象都指向同一个对象**/
		/**Tom,10000.0,Fri Dec 11 00:00:00 CST 2015**/
		/**Tom,11000.0,Fri Dec 11 00:00:00 CST 2015**/

		return cloned;
	}

	public void setHireDay(int year, int month, int day) {
		Date newHireday = new GregorianCalendar(year, month, day).getTime();
		hireDay.setTime(newHireday.getTime());
	}

	public void raiseSalary(double byPrecent){
		double raise = salary * byPrecent / 100;
		salary += raise;
	}

	/**重写Object类的toString方法**/
	public String toString(){
		return new StringBuffer().append(name).append(",").append(salary).append(",")
				.append(hireDay).toString();
	}
}

JAVA对象克隆可能会出现的问题的更多相关文章

  1. Java对象克隆(Clone)及Cloneable接口、Serializable接口的深入探讨

    Java对象克隆(Clone)及Cloneable接口.Serializable接口的深入探讨 Part I 没啥好说的,直接开始Part II吧. Part II 谈到了对象的克隆,就不得不说为什么 ...

  2. (转)Java对象克隆(Clone)及Cloneable接口、Serializable接口的深入探讨

    原文地址:http://blog.csdn.net/kenthong/article/details/5758884 Part I 没啥好说的,直接开始Part II吧. Part II 谈到了对象的 ...

  3. Java对象克隆详解

    原文:http://www.cnblogs.com/Qian123/p/5710533.html 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = appl ...

  4. java对象克隆复制

    原文链接:https://blog.csdn.net/ztchun/article/details/79110096 自己先简单描述总结一下:当想要将一个对象中已有的值直接给另外一个对象的时候,其实并 ...

  5. java对象克隆以及深拷贝和浅拷贝

    1.什么是"克隆"? 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不 ...

  6. JAVA对象克隆

    1> 为了获取对象的一份拷贝,我们可以利用Object类的clone()方法. 2> 在派生类中覆盖基类的clone(),并声明为public.3> 在派生类的clone()方法中, ...

  7. Java提高篇——对象克隆(复制)

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

  8. Java对象的克隆和深浅问题

    Java实现克隆的方式 Java实现克隆的方式有如下两种, 推荐采用实现Cloneable接口的方式 实现Cloneable接口, 重写clone方法, 调用父类的clone方法 还有另一种方法, 不 ...

  9. Java对象和集合的拷贝/克隆/复制

    昨天同事遇到了一个奇怪的问题,他需要将一个JavaBean拷贝一份,然后对新创建的Bean进行操作.但是他对新的Bean操作后,会影响旧的Bean的值.当听到这个问题的时候,我第一反应就是他的拷贝方法 ...

随机推荐

  1. html取地址栏参数的方法

    现在的人写的博客真是日常挖坑 闲的蛋疼 想把所有东西都转成jstl格式 有个界面是取地址栏的信息的 之前用的是 <%--不用jstl的方法直接传递--%> <%--String ro ...

  2. 线性回归(Linear Regression)均方误差损失函数最小化时关于参数theta的解析解的推导(手写)

    第一页纸定义了损失函数的样子, theta, X 和 y 的 shape, 以及最终的损失函数向量表现形式. 第二页纸抄上了几个要用到的矩阵求导公式,以及推导过程和结果. 要说明的是:推导结果与the ...

  3. LinkedList源码和并发问题分析

    1.LinkedList源码分析 LinkedList的是基于链表实现的java集合类,通过index插入到指定位置的时候使用LinkedList效率要比ArrayList高,以下源码分析是基于JDK ...

  4. PHP 实例 AJAX 投票

    AJAX 投票 在下面的实例中,我们将演示一个投票程序,通过它,投票结果在网页不进行刷新的情况下被显示. Do you like PHP and AJAX so far? Yes: No: 实例解释 ...

  5. cassandra 3.x官方文档(5)---探测器

    写在前面 cassandra3.x官方文档的非官方翻译.翻译内容水平全依赖本人英文水平和对cassandra的理解.所以强烈建议阅读英文版cassandra 3.x 官方文档.此文档一半是翻译,一半是 ...

  6. linux和android开发链接

    1.Tracy Mcgrady的专栏冰山一角:linux和Android底层开发,主要是mtk系列点击打开链接 2.郁闷Wednesday:嵌入式linux 单片机 android,点击打开链接 3. ...

  7. 整理的Java List Set Map是否有序,元素是否允许重复

    整理的Java List Set Map是否有序,元素是否允许重复的说明,如下图:

  8. 使用DB查询分析器实现异构数据源中数据表的相互访问

    1  引言   硕士程序员马根峰(CSDN专访马根峰:海量数据处理与分析大师的中国本土程序员)推出的个人作品----万能数据库查询分析器,中文版本DB 查询分析器.英文版本<DB Query A ...

  9. Vue 踩坑记

    参考: https://forum.vuejs.org/t/unknown-issues-in-change-event-of-radio-in-vue-2-x-webpack-2-x/11034 v ...

  10. python 3 黑色魔法元类初探

    最近读django源码,发现必须了解元类才能理解一些很神奇的行为. 发现元类实际上是控制class的创建过程.比如类B继承某个看似平淡无奇的类A之后,你在类B中定义的属性或方法可能会遭到彻底改变. 假 ...