使用clone( )和Cloneable接口
由Object类定义的绝大部分方法在本书其他部分讨论。而一个特别值得关注的方法是clone( )。clone( )方法创建调用它的对象的一个复制副本。只有那些实现Cloneable接口的类能被复制。
Cloneable接口没有定义成员。它通常用于指明被创建的一个允许对对象进行位复制(也就是对象副本)的类。如果试图用一个不支持Cloneable接口的类调用clone(
)方法,将引发一个CloneNotSupportedExcepti
on异常。当一个副本被创建时,并没有调用被复制对象的构造函数。副本仅仅是原对象的一个简单精确的拷贝。
复制是一个具有潜在危险的操作,因为它可能引起不是你所期望的副作用。例如,假如被复制的对象包含了一个称为obRef的引用变量,当副本创建时,副
本中的obRef如同原对象中的obRef一样引用相同的对象。如果副本改变了被obRef引用的对象的内容,那么对应的原对象也将被改变。这里是另一个
例子。如果一个对象打开一个I/O流并被复制,两个对象将可操作相同的流。而且,如果其中一个对象关闭了流,而另一个对象仍试图对I/O流进行写操作的
话,将导致错误。
由于复制可能引起问题,因此在Object内,clone(
)方法被说明为protected。这就意味着它必须或者被由实现Cloneable的类所定义的方法调用,或者必须被那些类显式重载以便它是公共的。让我们看关于下面每一种方法的例子。
下面的程序实现Cloneable接口并定义cloneTest( )方法,该方法在Object中调用clone(
)方法:
// Demonstrate the clone() method.
class TestClone implements Cloneable {
int a;
double b;
// This method calls Object's clone().
TestClone cloneTest() {
try {
// call clone in Object.
return (TestClone) super.clone();
} catch(CloneNotSupportedException e) {
System.out.println("Cloning not allowed.");
return this;
}
}
}
class CloneDemo {
public static void main(String args[]) {
TestClone x1 = new TestClone();
TestClone x2;
x1.a = 10;
x1.b = 20.98;
x2 = x1.cloneTest(); // clone x1
System.out.println("x1: " + x1.a + " " + x1.b);
System.out.println("x2: " + x2.a + " " + x2.b);
}
}
这里,方法cloneTest( )在Object中调用clone( )方法并且返回结果。注意由clone(
)方法返回的对象必须被强制转换成它的适当类型(TestClone)。
下面的例子重载clone(
)方法以便它能被其类外的程序所调用。为了完成这项功能,它的存取说明符必须是public,如下所示:
// Override the clone() method.
class TestClone implements Cloneable {
int a;
double b;
// clone() is now overridden and is public.
public Object clone() {
try {
// call clone in Object.
return super.clone();
} catch(CloneNotSupportedException e) {
System.out.println("Cloning not allowed.");
return this;
}
}
}
class CloneDemo2 {
public static void main(String args[]) {
TestClone x1 = new TestClone();
TestClone x2;
x1.a = 10;
x1.b = 20.98;
// here, clone() is called directly.
x2 = (TestClone) x1.clone();
System.out.println("x1: " + x1.a + " " + x1.b);
System.out.println("x2: " + x2.a + " " + x2.b);
}
}
由复制带来的副作用最初一般是比较难发现的。通常很容易想到的是类在复制时是很安全的,而实际却不是这样。一般在没有一个必须的原因的情况下,对任何类都不应该执行Cloneable。
浅复制和深复制来说一下,首先需要了解对象深、浅复制的概念:
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
此处,写一个深浅复制的例子:
public class Prototype implements Cloneable, Serializable {
- private static final long serialVersionUID = 1L;
- private String string;
- private SerializableObject obj;
- /* 浅复制 */
- public Object clone() throws CloneNotSupportedException {
- Prototype proto = (Prototype) super.clone();
- return proto;
- }
- /* 深复制 */
- public Object deepClone() throws IOException, ClassNotFoundException {
- /* 写入当前对象的二进制流 */
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(bos);
- oos.writeObject(this);
- /* 读出二进制流产生的新对象 */
- ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
- ObjectInputStream ois = new ObjectInputStream(bis);
- return ois.readObject();
- }
- public String getString() {
- return string;
- }
- public void setString(String string) {
- this.string = string;
- }
- public SerializableObject getObj() {
- return obj;
- }
- public void setObj(SerializableObject obj) {
- this.obj = obj;
- }
- }
- class SerializableObject implements Serializable {
- private static final long serialVersionUID = 1L;
- }
使用clone( )和Cloneable接口的更多相关文章
- Cloneable接口和Object的clone()方法
为什么要克隆 为什么要使用克隆,这其实反映的是一个很现实的问题,假如我们有一个对象: public class SimpleObject implements Cloneable { private ...
- Java对象克隆(Clone)及Cloneable接口、Serializable接口的深入探讨
Java对象克隆(Clone)及Cloneable接口.Serializable接口的深入探讨 Part I 没啥好说的,直接开始Part II吧. Part II 谈到了对象的克隆,就不得不说为什么 ...
- (转)Java对象克隆(Clone)及Cloneable接口、Serializable接口的深入探讨
原文地址:http://blog.csdn.net/kenthong/article/details/5758884 Part I 没啥好说的,直接开始Part II吧. Part II 谈到了对象的 ...
- java开发——Cloneable接口、clone()方法和深浅拷贝
1.实现Cloneable接口表明该类的对象是允许克隆的. 2.允许克隆的意思是:可以调用clone()方法. 3.深拷贝还是浅拷贝,取决于如何重写Object的clone()方法. 4.原对象和克隆 ...
- Java 深拷贝、浅拷贝及Cloneable接口
Cloneable接口是一个空接口,仅用于标记对象,Cloneable接口里面是没有clone()方法,的clone()方法是Object类里面的方法!默认实现是一个Native方法 protecte ...
- java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))
Java提高篇--对象克隆(复制)(转自:http://www.cnblogs.com/Qian123/p/5710533.html#_label0) 阅读目录 为什么要克隆? 如何实现克隆 浅克 ...
- java对象 深度克隆(不实现Cloneable接口)和浅度克隆
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt128 为什么需要克隆: 在实际编程过程中,我们常常要遇到这种情况:有一个对象 ...
- Java中的Cloneable接口理解
Cloneable接口是一个标记接口,也就是没有任何内容,定义如下: 这里分析一下这个接口的用法,clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类 ...
- java Comparable 和 Cloneable接口
Comparable接口定义了compareTo方法,用于比较对象. 例如,在JavaAPI中,Integer.BigInteger.String以及Date类定义如下 Cloneable接口 Clo ...
随机推荐
- jQuery coveringBad 效果对比
Covering-Bad 是一个可拉动大小的元素,覆盖在原有的元素上面,从而两者进行对比. 在线实例 实例演示1 实例演示2 使用方法 <div class="covered&q ...
- eclipse导入svn项目,项目却没有svn的标记
现象: eclipse(已经装有svn插件)导入svn项目,项目没有svn的标记. 原因: 1.可能是由于你的svn eclipse插件,也就是subclipse,与svn的客户端版本不匹配. 解决 ...
- python基础之基本算法和装饰器
1.冒泡排序 关于冒泡排序实现大小比较,大索引会向后移动,这次循环将最大数值直接移动至最后. li = [,,,,] ): ]: temp = li[i] li[i] = li[i + ] li[i ...
- SAP技术相关Tcode
ABAP的常用tcode 开发----------------------------------------------- SE51 屏幕制作 SE91 MESSAGE OBJECT SE80 ...
- ubuntu14.0安装arm-linux-gcc交叉编译环境
1.下载文件: 安装包:arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz 下载地址 http://pan.baidu.com/s/1pJwQ6Sj 2.开始安装(建议大 ...
- iOS阅读器实践系列(一)coretext纯文本排版基础
前言:之前做了公司阅读类的App,最近有时间来写一下阅读部分的实现过程,供梳理逻辑,计划会写一个系列希望能涉及到尽量多的方面与细节,欢迎大家交流.吐槽.拍砖,共同进步. 阅读的排版用的是coretex ...
- NSString、NSArray、NSDictionary和NSData的数据存储
#import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...
- iOS网络检测Reachability 使用 Demo,可检测2、3、4G
你可以在Github下载这个Demo https://github.com/JanzTam/Reachability_Demo 首先,引入系统的Reachability类,不知道怎么引入的话,在Xco ...
- Android性能优化(一)
Android性能优化典范 1.大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能. 从设计师的角度,他们希望App能够有更多的动画,图片等时尚元素来实现流畅的用户体验. 但是Android ...
- 【mysql】关于innodb_file_format
一.几条mysql命令 通过以下命令看一下mysql中 innodb_file_format的配置 mysql> show engines; +--------------------+---- ...