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

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

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

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. 用js来实现那些数据结构12(散列表)

    上一篇写了如何实现简单的Map结构,因为东西太少了不让上首页.好吧... 这一篇文章说一下散列表hashMap的实现.那么为什么要使用hashMap?hashMap又有什么优势呢?hashMap是如何 ...

  2. C# 虹软SDK视频人脸识别和注册

    一,准备工作 1.Afoge视频参数类 using AForge.Video.DirectShow; using System; using System.Collections.Generic; u ...

  3. Js删除数组函数

    引用地址:http://www.398588.com/Article/T8/96.aspx 众所周知大家都应该知道delete的用法,用来删除对象或者删除数组等,如果是删除对象除数组以外可能可以删除的 ...

  4. jQuery 选择器 prop() 和attr()

    Day30 jQuery 1.1.1.1 什么是jQuery? n jQuery是javaScript的前端框架.对常见的对象和常用的方法进行封装,使用更方便. 它兼容CSS3,还兼容各种浏览器.文档 ...

  5. 解释session

    我理解的session就是,多个页面都要使用某一个或一些数据,这时就可以用session,将数据暂时保存起来,这样其他的页面开启session,就能将那些数据拿出来使用.

  6. plsql和tsql常用函数比较

    数学函数 .绝对值 S:) value O:) value from dual .取整(大) S:select ceiling(-1.001) value O:select ceil(-1.001) ...

  7. 潜谈IT从业人员在传统IT和互联网之间的择业问题(上)-传统乙方形公司

    外包能去吗?项目型公司如何?甲方比乙方好?互联网公司就一定好吗? 相信许多从业者在经历了3-5年的工作期后都会带着这样的疑问或者疑惑. 2012年-2014年间,曾经面试过500人,亲身面试的也有15 ...

  8. 20160218.CCPP体系详解(0028天)

    程序片段(01):加法.c 内容概要:字符串计算表达式 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <st ...

  9. hive高阶1--sql和hive语句执行顺序、explain查看执行计划、group by生成MR

    hive语句执行顺序 msyql语句执行顺序 代码写的顺序: select ... from... where.... group by... having... order by.. 或者 from ...

  10. 【Android应用开发】Android 蓝牙低功耗 (BLE) ( 第一篇 . 概述 . 蓝牙低功耗文档 翻译)

    转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50515359 参考 :  -- 官方文档 : https://develope ...