`

java clone()方法理解

阅读更多
编码过程中需要用到clone方法,以前看过不少,长时间不用记得不是很清楚,于是google了一下发现好多都说的比较乱,于是重新查了下资料做个记录。
首先是java6 api中Cloneable接口的描述

A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.

Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.

By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. See Object.clone() for details on overriding this method.

Note that this interface does not contain the clone method. Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface. Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.

主要部分是第一段,意思是:实现了Cloneable接口的类可以合法的使用clone方法来创建一个该类的属性对属性复制的对象。我的理解是clone方法返回一个新对象,该对象的属性值是对原对象属性值的简单复制。
下面是java6 api中对Obejct对象clone方法的注释

Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression:
 x.clone() != x
will be true, and that the expression:
 x.clone().getClass() == x.getClass()
will be true, but these are not absolute requirements. While it is typically the case that:
 x.clone().equals(x)
will be true, this is not an absolute requirement.
By convention, the returned object should be obtained by calling super.clone. If a class and all of its superclasses (except Object) obey this convention, it will be the case that x.clone().getClass() == x.getClass().

By convention, the object returned by this method should be independent of this object (which is being cloned). To achieve this independence, it may be necessary to modify one or more fields of the object returned by super.clone before returning it. Typically, this means copying any mutable objects that comprise the internal "deep structure" of the object being cloned and replacing the references to these objects with references to the copies. If a class contains only primitive fields or references to immutable objects, then it is usually the case that no fields in the object returned by super.clone need to be modified.

The method clone for class Object performs a specific cloning operation. First, if the class of this object does not implement the interface Cloneable, then a CloneNotSupportedException is thrown. Note that all arrays are considered to implement the interface Cloneable. Otherwise, this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.

The class Object does not itself implement the interface Cloneable, so calling the clone method on an object whose class is Object will result in throwing an exception at run time.

大概的主要意思是
1.x.clone() != x,意思是clone方法返回的对象是新生成的对象与原来对象的地址不相等。
2. x.clone().getClass() == x.getClass(),两个对象的类是相同的。
3. x.clone().equals(x),这点需要着重说明:这个不是clone方法的绝对要求,这个主要看equals方法的实现。
4.按照惯例每个实现Cloneable接口的类的clone()方法的对象需要由super.clone()来生成,这样可以保证该类的父类(除了Object类)都满足条件2.
5.在返回由super.clone()生成的对象前需要根据需求适当的修改生成对象的属性,这就涉及到深拷贝和浅拷贝。因为Object的clone()方法只是对简单的属性值复制,所以如果对象中有可变的数据结构(类似数组,链表,对象等引用类型)需要进行深拷贝。而如果只是基本类型,或者不可变的对象(如String对象)则只需要浅拷贝。

        另外需要注意的是Object.clone()方法是protect类型的,我们在覆盖的时候需要修改为public类型。
下面这段代码是具体类cloe()方法浅拷贝一般写法

abstract public class X implements Cloneable {
        public X clone() throws CloneNotSupportedException {
                return (X) super.clone();
        }
}

这是深拷贝的一般写法
public Z clone() throws CloneNotSupportedException {
                Z newZ = (Z) super.clone();
                newZ.someABC = someABC.clone();
 
                return newZ;

下面贴出测试clone方法的测试代码
import java.util.Arrays;
/**
 * 
 * @author lwj.charles
 * 
 */
public class CloneTest {
	/**
	 * 测试类A
	 */
	class A implements Cloneable{
		private int num; //不可变属性,int类型
		private String str;//不可变属性,String对象是不可修改的。
		public A(int num, String str){
			this.num = num;
			this.str = str;
		}
		public A clone() throws CloneNotSupportedException{
			return (A)super.clone();
		}
		public void display(){
			System.out.println("-----begin-----");
			System.out.println("int:" + num);
			System.out.println("String:" + str);
			System.out.println("-----end-----");
		}
	}
	/**
	 * 测试类B
	 */
	class B implements Cloneable{
		private int num; //不可变属性
		private int [] nums;//可变属性
		public B(int num, int[] nums){
			this.num = num;
			this.nums = nums;
		}
//		/**
//		 * clone()方法的浅拷贝实现
//		 */
//		public B clone() throws CloneNotSupportedException{
//			return (B)super.clone();
//		}
		/**
		 * clone()方法的深拷贝实现
		 */
		public B clone() throws CloneNotSupportedException{
			B b = (B)super.clone();
			b.nums = Arrays.copyOf(b.nums, b.nums.length);
			return b;
		}
		public void display(){
			System.out.println("-----begin-----");
			System.out.println("int:" + num);
			System.out.println("Arrays:" + nums);
			System.out.println("nums[1]:" + nums[1]);
			System.out.println("-----end-----");
		}
	}
	public static void main(String [] args) throws CloneNotSupportedException{
		CloneTest ct = new CloneTest();
		
		//测试对象的属性为不可变属性。用浅拷贝即可满足要求。
		CloneTest.A a1 = ct.new A(1,"test1");
		CloneTest.A a2 = a1.clone();
		a2.num = 2;
		a2.str = "test2";
		a1.display();
		a2.display();
		
		//测试对象的属性为可变属性。注意对比试用浅拷贝和深拷贝的结果。
		int [] nums = {1,2,3};
		CloneTest.B b1 = ct.new B(1,nums);
		CloneTest.B b2 = b1.clone();
		b2.num = 2;
		b2.nums[1] = -2;
		b1.display();
		b2.display();
	}
}

分享到:
评论

相关推荐

    Java的Object类讲解案例代码 equals()、hashCode()、finalize()、clone()、wait()

    本案例代码将详细展示Object类的使用方法,并提供一些实际场景下的案例,以帮助开发者更好地理解和运用这些方法。 这份案例代码适合以下人群: Java初学者:如果你是刚开始学习Java编程,那么Object类是一个重要的...

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

    7.11 小结:多方位理解Java方法 191 7.12 习题 192 第8章 Java中的包(Package)命名习惯和注释 193 教学视频:43分钟 8.1 Java中的包(Package) 193 8.1.1 Java中的包 193 8.1.2 在Eclipse中使用包 194 ...

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

    7.11 小结:多方位理解Java方法 191 7.12 习题 192 第8章 Java中的包(Package)命名习惯和注释 193 教学视频:43分钟 8.1 Java中的包(Package) 193 8.1.1 Java中的包 193 8.1.2 在Eclipse中使用包 194 ...

    java 编程入门思考

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

    Java初学者入门教学

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

    java联想(中文)

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

    java深入理解浅拷贝和深拷贝

    拷贝对象是java中经常会遇到的问题。java中存在两种类型,基础类型和引用类型。...Object对象中提供了一个clone方法,来供我们对java对象进行拷贝。 protected native Object clone() throws CloneNot

    java面向对象之JVM创建及分配策略方法详解.docx

    前言 Java是面向对象的语言,所谓“万事万物皆对象”就是Java是基于对象来设计程序的,没有对象程序就无法运行(8大基本类型除外),那么对象是如何创建的?...为了便于说明和理解,下文仅针对new出来的对象进行讨论。

    JAVA_Thinking in Java

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

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

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

    Thinking in Java简体中文(全)

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

    涵盖了90%以上的面试题

    java中的clone方法有什么作用 面向对象有哪些特征 面向对象的开发方式有什么优点 组合和继承有什么区别 多态的实现机制是什么 重写和重载的区别 抽象类和接口有什么区别 break如果跳出多重循环 final,finally和...

    Java面试宝典-经典

    21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstract的method是否可同时是...

    Java面试宝典2010版

    21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstract的method是否可同时是...

    java面试题大全(2012版)

    21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstract的method是否可同时是...

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

    HMM模型源代码,非常适合新手使用,理解模型原理,若有问题欢迎咨询本人,一起学习学习!

    Java核心技术II(第8版)

    10.4.5 远程对象与equals、hashCode和clone方法 10.5 远程对象激活 10.6 Web Services与JAX-WS 10.6.1 使用JAX-WS 10.6.2 Web服务的客户端 10.6.3 Amazon的E-Commerce服务 第十一章 脚本、编译与注解处理 11.1 Java...

    对象克隆(clone)详解.docx

    查看了很多文章对于clone()方法讲解都不慎透彻,特别是对于深层克隆的讲解语言晦涩难懂,很难理解,包括Oracle公司出版的JDK帮助文档也讲的不清楚,本人通过具体实践通过浅显易懂的语言详细讲解了clone()方法。...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

Global site tag (gtag.js) - Google Analytics