Java的对象都是引用,当将一个对象赋值给另外一个对象的时候, 也就是说指针(当然,java没有指针的概念)同指向同一块内存地址。
这个时如果对一个对象进行修改,也必然会修改另外一个对象的值,这明显不是我们想要的.
解决这个问题,可以引入克隆技术,我们可以克隆一个对象出来,使得对克隆出来的对象修改不会改变原始对象的值。
克隆分为:浅克隆和深克隆。
浅克隆是指:浅克隆只是克隆当前的对象,不克隆该对象所应用的对象
深克隆是指:深克隆不但克隆当前的对象,而且还克隆该对象所引用的对象
Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。
Object 类的 clone 方法执行特定的克隆操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出
CloneNotSupportedException。 注意:所有的数组都被视为实现接口 Cloneable。
否则,此方法会创建此对象的类的一个新实例,并像通过分配那样, 严格使用此对象相应字段的内容初始化该对象的所有字段; 这些字段的内容没有被自我克隆。
所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。
我们知道,Java是纯面向对象的程序设计语言。
Java里,所有的类的顶级父类都是java.lang.Object类,
也就是说,如果一个类没有显示 申明继承关系,它的父类默认就是java.lang.Object。
有一个很简单的方法可以证明这一点,我们写一个Test类,如下:
public class Test {
public void someMethod() {
super.clone();
}
}
里面调用了super.clone(),编译时并不报错。其实clone()方法为java.lang.Object类提供的一个 protected型方法。
对象克隆
本文通过介绍java.lang.Object#clone()方法来说明Java语言的对象克隆特性。
java.lang.Object#clone()方法由java.lang.Object加以实现,主要对对象本身加以克隆。
首先我们看看下面的例子:
编译执行TestClone,打印出:
C:\clone>javac *.java
C:\clone>java TestClone
Clone Not Supported
C:\clone>
说明MyClone#clone()方法调用super.clone()时抛出了CloneNotSupportedException异常,不 支持克隆。
为什么父类java.lang.Object里提供了clone()方法,却不能调用呢?
原来,Java语言虽然提供了这个方法,但考虑到安全问题,
一方面将clone()访问级别设置为protected型,以限制外部类访问;
另一方面,强制需要提供clone功能的子类实现java.lang.Cloneable接口,
在运行期,JVM会检查调用clone()方法的 类,如果该类未实现java.lang.Cloneable接口,则抛出CloneNotSupportedException异常。
java.lang.Cloneable接口是一个空的接口,没有申明任何属性与方法。该接口只是告诉JVM,该接口的实现类需要开放“克隆”功 能。
我们再将MyClone类稍作改变,让其实现Cloneable接口:
class MyClone implements Cloneable {
...//其余不做改变
}
编译执行TestClone,打印出:
C:\clone>javac *.java
C:\clone>java TestClone
clone1
myClone2 equals myClone1 : false
C:\clone>
根据结果,我们可以发现:
1,myClone1.clone()克隆了跟myClone1具有相同属性值的对象
2,但克隆出的对象myClone2跟myClone1不是同一个对象(具有不同的内存空间)
小结:
如果要让一个类A提供克隆功能,该类必须实现java.lang.Cloneable接口,并重载 java.lang.Object#clone()方法。
对象的深层次克隆
上例说明了怎么样克隆一个具有简单属性(String,int,boolean等)的对象。
但如果一个对象的属性类型是List,Map,或者用户自定义的其他类时,克隆行为是通过怎样的方式进行的?
很多时候,我们希望即使修改了克隆后的对象的属性值,也不会影响到原对象,这种克隆我们称之为对象的深层次克隆。
怎么样实现对象的深层次克隆呢?
验证对象的克隆方式
为了验证对象的克隆方式,我们对上面的例子加以改进,如下
运行结果:
myClone2.name=clone1 myClone2.boolValue=true myClone2.intValue=100
myClone2.listValue.size():3
myClone2.element.equals(myClone1.element):true
myClone2.element.name:element1
myClone1.listValue.size():4
myClone1.element.name:Element2
我们发现,对于对象里的List,Element等复合属性,super.clone()只是简单地赋值,没有采取克隆手段。
也就是说,修改被克 隆后的对象值,会影响到原对象。
怎么进行深层次的克隆呢?
答案是,我们只能手动在重载的clone()方法里,对属性也分别采用克隆操作。当然条件是,属性类也得支持克隆操作
深层次的克隆操作往往存在效率问题,尤其是需要让List,Map等集合类也支持深层次的克隆操作时。
总结:
本文结合范例,比较深入地介绍了Java语言的克隆属性,以及克隆的实现方法等。
同时分析了深层次克隆的概念,实现,以及存在的问题等。 但是有没有更好的方法呢?当然,是有的,串行化来实现。
如果实现深克隆?
一个方法自然是重写clone方法,添加如order.items=(LineItems)items.clone()的语句,也就是人为地添加对引用对象的复制。这个方法的缺点是如果引用对象有很多,或者说引用套引用很多重,那么太麻烦了。业界常用的方法是使用串行化然后反串行化的方法来实现深克隆。由于串行化后,对象写到流中,所有引用的对象都包含进来了,所以反串行化后,对等于生成了一个完全克隆的对象。绝!
可借鉴:http://blog.csdn.net/accp_fangjian/article/details/2423252
这个方法的要求是对象(包括被引用对象)必须事先了Serializable接口,否则就要用transient关键字将其排除在复制过程中。
再举一个例子:
分享到:
相关推荐
NULL 博文链接:https://gegeyi.iteye.com/blog/1562016
学习java深克隆与浅克隆,希望对你有用
java 深克隆 浅克隆
浅克隆: package testclone; public class ShallowClone implements Cloneable { public String name; public String[] name2; public ShallowClone() { name2 = new String[2]; } public Object clone() {...
java 深克隆浅克隆···············
Java对象的深克隆与浅克隆详解.zip
在本篇文章中我们给大家分享了关于java对象中浅克隆和深克隆的相关知识点和相关代码内容,有兴趣的朋友们学习下。
主要介绍了java 对象的克隆的相关资料,这里对浅克隆和深克隆进行了实例分析需要的朋友可以参考下
有关Java中的克隆技术的详细讲述,其中讲解了“浅复制”和“深复制”的用法和区别,继承了Java中的封装类Cloneable
浅拷贝(浅复制、浅克隆)、深拷贝(深复制、深克隆)实战工程,IDEA搭建
Java对象的复制与克隆,包含浅复制和深层复制。 免费下载啦,绝对值得一看。
1.浅复制与深复制概念 ...⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
android 浅复制和深复制-Java Generic Deep Copy 篇
主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下
本篇文章是对JAVA深度克隆与浅度克隆的区别进行了详细的分析介绍,需要的朋友参考下
示例Bean.java 公共类ExampleBean { 私有 int id; 私人用户用户; 私人名单名单; 公共 int getId() { 返回ID; } 公共无效setId(int id){ 这个.id = id; } 公共用户 getUser() { 返回用户; } ...
java设计模式【之】原型模式、深拷贝与浅拷贝【源码】【场景:克隆羊】 * 原型模式(Prototype) * 实现方式: * 需要被克隆的 class类, 重写Object中的clone()方法,并实现Cloneable接口(否则报错 ...
Java克隆(Clone)是Java语言的特性之一,本篇文章主要介绍了Java中的Clone机制是如何工作的,需要的朋友可以参考下
概述对象克隆库。 支持可扩展的浅层和深层对象克隆策略。用法下面是一个关于如何使用库的示例 // Example TestObject clone = new ObjectCloner().deepClone(originalTestObject);有关更多示例,请参阅 junit 测试...
主要介绍了Java实现克隆的三种方式,结合实例形式总结分析了java浅复制、深复制以及使用serializable实现深复制的相关操作技巧,需要的朋友可以参考下