- 浏览: 188413 次
- 性别:
- 来自: 杭州
最新评论
-
wahahachuang5:
web实时推送技术使用越来越广泛,但是自己开发又太麻烦了,我觉 ...
转发:websocket 通信协议介绍 -
爱很执着:
好
Java多线程同步机制(synchronized) -
我在路上看风景:
不错啊,看完了,疑惑不存在了。 新浪微博@最美最好的你
Java多线程同步机制(synchronized) -
hbiao68:
写得很好,受教了
Java Resource路径总结二 -
JamesLiuX:
有Freelancer的老鸟吗,求组队!
Freelancer
转载
我们知道,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加以实现,主要对对象本身加以克隆。
首先我们看看下面的例子:
public class TestClone { public static void main(String[] args) { MyClone myClone1 = new MyClone("clone1"); MyClone myClone2 = (MyClone)myClone1.clone(); if (myClone2 != null) { System.out.println(myClone2.getName()); System.out.println("myClone2 equals myClone1: " + myClone2.equals(myClone1)); } else { System.out.println("Clone Not Supported"); } } }
class MyClone { private String name; public MyClone(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { return null; } }
编译执行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()方法。
public class A extends Cloneable { public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { //throw (new InternalError(e.getMessage())); return null; } } }
对象的深层次克隆
上例说明了怎么样克隆一个具有简单属性(String,int,boolean等)的对象。
但如果一个对象的属性类型是List,Map,或者用户自定义的其他类时,克隆行为是通过怎样的方式进行的?
很多时候,我们希望即使修改了克隆后的对象的属性值,也不会影响到原对象,这种克隆我们称之为对象的深层次克隆。怎么样实现对象的深层次克隆呢?
验证对象的克隆方式
为了验证对象的克隆方式,我们对上面的例子加以改进,如下(为了节省篇幅,我们省略了setter与getter方法):
public class TestClone { public static void main(String[] args) { //为克隆对象设置值 MyClone myClone1 = new MyClone("clone1"); myClone1.setBoolValue(true); myClone1.setIntValue(100); //设置List值 List <Element>listValue = new ArrayList<Element>(); listValue.add(new Element("ListElement1")); listValue.add(new Element("ListElement2")); listValue.add(new Element("ListElement3")); myClone1.setListValue(listValue); //设置Element值 Element element1 = new Element("element1"); myClone1.setElement(element1); //克隆 MyClone myClone2 = (MyClone)myClone1.clone(); if (myClone2 != null) { //简单属性 System.out.println("myClone2.name=" + myClone2.getName() + " myClone2.boolValue=" + myClone2.isBoolValue() + " myClone2.intValue=" + myClone2.getIntValue() ); //复合属性(List<Element>与Element) List clonedList = myClone2.getListValue(); Element element2 = myClone2.getElement(); System.out.println("myClone2.listValue.size():" + clonedList.size()); System.out.println("myClone2.element.equals(myClone1.element):" + element2.equals(element1)); System.out.println("myClone2.element.name:" + element2.getName()); //下面我们测试一下myClone2.element是否等于myClone1.element //以及myClone2.listValue是否等于myClone1.listValue //为此,我们修改myClone2.element与myClone2.listValue,如果myClone1的相应值也跟着被修改了,则它们引用的是同一个内存空间的变量,我们认为它们相等 clonedList.add("ListElement4"); System.out.println("myClone1.listValue.size():" + listValue.size()); element2.setName("Element2"); System.out.println("myClone1.element.name:" + element1.getName()); } else { System.out.println("Clone Not Supported"); } } }
class MyClone implements Cloneable { private int intValue; private boolean boolValue; private String name; private List <Element>listValue; private Element element; public MyClone(String name) { this.name = name; } ...//setter与getter方法(略) } class Element implements Cloneable { private String name; public Element (String name) { this.name = name; } ...//setter与getter方法(略) }
编译执行TestClone,打印出:
C:\clone>javac *.java
C:\clone>java TestClone
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
myClone2 equals myClone1: false
C:\clone>
我们发现,对于对象里的List,Element等复合属性,super.clone()只是简单地赋值,没有采取克隆手段。也就是说,修改被克隆后的对象值,会影响到原对象。
怎么进行深层次的克隆呢?
答案是,我们只能手动在重载的clone()方法里,对属性也分别采用克隆操作。当然条件是,属性类也得支持克隆操作
class MyClone implements Cloneable { ... public Object clone() { try { MyClone myClone = (MyClone)super.clone(); //分别对属性加以克隆操作 myClone.element = this.element.clone(); myClone.listValue = new ArrayList(); for (Element ele:this.listValue) { myClone.listValue.add(ele.clone()); } return myClone; } catch (CloneNotSupportedException e) { return null; } } ... }
//让Element类也支持克隆操作 class Element implements Cloneable { ... public Element clone() { try { return (Element)super.clone(); } catch (CloneNotSupportedException e) { return null; } } }
深层次的克隆操作往往存在效率问题,尤其是需要让List,Map等集合类也支持深层次的克隆操作时。
总结:
本文结合范例,比较深入地介绍了Java语言的克隆属性,以及克隆的实现方法等。同时分析了深层次克隆的概念,实现,以及存在的问题等。 但是有没有更好的方法呢?当然,是有的,串行化来实现。
发表评论
-
Java集合框架
2014-08-19 18:36 541Java Collections Framework是Ja ... -
java线程安全总结
2011-11-11 10:38 1042总结的很好的java线程安全文章 http://www.it ... -
深入分析 Java 中的中文编码问题
2011-08-29 14:39 895一篇比较深入清晰的中文编码分析文章: http://www. ... -
使用dom4j四种读取xml文件的方法
2011-07-18 11:10 1370转:http://blog.163.com/chenhui_j ... -
Java Resource路径总结二
2011-07-15 14:02 11069Class.getResource()与Class.getRe ... -
java 读取配置文件(properties)
2011-07-11 17:59 1238使用J2SE API读取Properties文件的六种方法 ... -
常见的海量数据处理方法
2011-07-04 12:01 1034转:http://www.iteye.com/topi ... -
Servlet 工作原理解析
2011-06-30 12:04 1250Servlet 工作原理解析 http://www.ibm. ... -
java调用oracle序列方法
2011-06-14 15:29 24411. 创建oracle序列 create sequence ... -
java调用msyql函数和存储过程的方法
2011-06-14 14:11 1296java调用msyql函数和存储过程的方法 2009年0 ... -
java多线程专题测试五:死锁
2011-06-12 23:36 3147死锁 1、如何确认死锁的发生? Java虚拟机死锁发生 ... -
java多线程专题测试四:JAVA内存模型
2011-06-12 23:35 1109JAVA内存模型 1、什么是内存模型,什么是可见性? ... -
java多线程专题测试三:concurrent包
2011-06-09 13:07 1284concurrent包 1、Lock和Condition ... -
java多线程专题测试二:多线程读写安全
2011-06-09 12:27 1782多线程读写安全 1、sync ... -
java多线程总结
2011-06-09 10:45 967线程:是指进程中的一个执行流程。 线程与进程的区别:每个进程 ... -
java多线程专题测试一:基础知识
2011-06-09 00:07 1296一. 基础知识 1. 进程和 ... -
Java发送Http请求,解析html返回
2011-06-07 23:13 932http://caspers.iteye.com/blog/2 ... -
Java中四种XML解析技术的学习与比较
2011-06-07 16:56 1025转:http://blog.sina.com.cn/s ... -
HTTP内容格式详细说明2(协议)
2011-06-02 16:44 13046 响应头域 响应头域允 ... -
HTTP内容格式详细说明1(协议)
2011-06-02 00:28 1083前言 HTTP 消息由客户端到服务器的请求和服务器 ...
相关推荐
Java中的clone方法详解_动力节点Java学院,动力节点口口相传的Java黄埔军校
### Java中的`clone`方法详解:浅拷贝与深拷贝 #### 一、引言 在Java中,`clone`方法提供了一种快速复制对象的方式。它属于`Object`类的一部分,但需要显式地在子类中声明并实现`Cloneable`接口才能正常使用。本文...
Java中的克隆(Clone)机制是一种创建对象副本的方法,它允许程序员复制一个对象的状态,而不会影响原始对象。克隆在编程中常用于创建对象的独立副本,使得新副本与原对象之间相互独立,对其中一个对象的修改不会...
Java中的`clone`方法是Java语言提供的一种复制对象的机制,它允许创建一个现有对象的副本,这个副本具有与原始对象相同的状态,但它们是独立的实体,对其中一个对象的修改不会影响另一个。`clone`方法是Java `Object...
Java中的clone方法详解 在Java语言中,clone方法是一个非常重要的概念,它允许对象被复制,从而创造出一个新的对象。下面我们将详细介绍Java中的clone方法,并讨论它的实现机制和应用场景。 什么是clone方法 ...
Java 中 clone() 的使用方法 Java 中的 clone() 方法是对象的复制方法,其主要作用是创建一个与原对象相同的新对象。下面将详细介绍 Java 中 clone() 方法的使用方法。 什么是 clone() 方法? clone() 方法是 ...
Java中的数组复制(clone与arraycopy)代码详解 Java中的数组复制是通过clone和arraycopy两个方法来实现的。clone方法是Object类的protected方法,用于创建对象的副本,而arraycopy是System类的静态方法,用于将一...
【对象克隆(clone)详解】 对象克隆是Java编程中的一个重要概念,它允许我们创建一个已有对象的副本,而不影响原始对象。在Java中,克隆主要涉及到`Object`类中的`clone()`方法,以及两种不同的克隆类型:浅克隆和...
首先,`clone()`方法是Java中的一个内置功能,它允许我们创建一个对象的浅拷贝。对于基本类型的数组,`clone()`会创建一个新的数组,然后复制原数组的所有元素到新数组中。然而,对于引用类型的数组(如对象数组),...
【Java原型模式详解】 原型模式(Prototype Pattern)是一种创建型设计模式,它的主要目标是通过复制现有的对象来创建新对象,以减少重复的构造过程,提高性能。在Java中,原型模式通常涉及到对象的克隆操作,即...
在Java中,浅拷贝可以通过实现`Cloneable`接口并重写`clone()`方法来完成。以下是一个简单的浅拷贝示例: ```java public class Person implements Cloneable { private String name; private int age; private ...
### Java 高级特性详解 #### 一、`hashCode` `hashCode` 方法是 `Object` 类中的一个方法,用于返回对象的哈希码值。在 Java 中,哈希码经常被用于实现散列表(如 `HashMap` 和 `HashSet`)。为了确保散列表的正确...
### Java软件开发实战:Java基础与案例开发详解 #### 6-2 Object类 在Java编程语言中,`Object`类扮演着极其重要的角色。它位于`java.lang`包内,是所有Java类的直接或间接父类。这意味着每一个自定义的类(除非...
Java 设计模式 - 原型模式详解 原型模式是 Java 设计模式之一,它用于创建对象时,指定创建对象的类型,并通过拷贝这些原型创建新的对象。该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原...
Java 函数习惯用法详解 Java 函数习惯用法是 Java 编程中非常重要的一部分,它直接影响着程序的效率和可读性。下面将对 Java 函数习惯用法进行详细的解释和总结。 一、equals() 函数 equals() 函数是 Java 中最...
这个压缩包文件"详解Java中Object 类的使用.rar"包含了对Java中Object类的深入探讨,通过阅读其中的"详解Java中Object 类的使用.txt"文本,我们可以了解到关于Object类的一些关键知识点。 1. **对象的创建与类型...