- 浏览: 540075 次
- 性别:
- 来自: 南京
-
文章分类
- 全部博客 (168)
- java基础 (22)
- 面向对象编程 (2)
- 集合 (4)
- I/O操作 (5)
- 多线程 (9)
- java高级特性 (8)
- 网络编程 (0)
- sql基础 (23)
- JDBC (1)
- 数据结构与算法 (20)
- 软件测试 (1)
- 程序员小知识 (2)
- WEB开发 (15)
- 其他 (11)
- Struts (3)
- Hibernate (8)
- Spring (4)
- 设计模式 (5)
- java基础快速总结 (1)
- 正则表达式 (3)
- UML (3)
- XML操作 (0)
- 编译原理 (1)
- tomcat (2)
- EJB (0)
- javascript (4)
- 个人系统设计 (1)
- Extjs (3)
- 面试题总结 (4)
- 技术大综合 (2)
- 最经需要搞好多的开源软件,集中下 (0)
- java重写hashcode的分析(转) (1)
最新评论
-
jerry.zhao:
ybzshizds 写道这种用工厂模式解决的办法其实还是有一个 ...
InitialContext和lookup -
小土豆内特:
static class Queue
java实现队列 -
leizisdu:
感谢楼主讲解、分享!
工厂模式 -
kchiu:
写了没什么用
EXT组件xtype简介 -
u010271301:
大哥 能描述的跟详细点么?
浅谈write(byte[] b)和write(byte[] b,int off,int len)的区别
我觉的这篇文章讲的很透彻很明了就照抄过来啦。希望与大家分享
我们知道,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语言的克隆属性,以及克隆的实现方法等。同时分析了深层次克隆的概念,实现,以及存在的问题等。 但是有没有更好的方法呢?当然,是有的,串行化来实现。
下一篇我们就来看一下如何利用串行化实现深克隆
发表评论
-
thingking in java的所见所闻
2010-09-07 19:54 1174今天终于翻开thinking in java一书,发掘里面的奥 ... -
java基础注意的误区
2010-08-12 13:46 11461.replace String a="| ... -
基础题集
2010-06-20 10:48 1085import java.util.ArrayList; ... -
浅复制和深复制的代码实现
2010-06-02 13:20 1261演示一:浅复制 public class Student ... -
java求保留2位有效小数
2010-05-28 11:35 3449/** * 求出保留2位有效小数 */ public ... -
native的作用
2010-05-27 09:01 1234native的作用 使用native关键字说明这个方法是原生 ... -
classloader原理
2010-05-12 22:21 1891What is ClassLoader? 与普通程 ... -
JVM认识
2010-05-12 22:08 1185首先看一个下java运行过程: Java Virtual ... -
jvm垃圾回收机制
2010-05-12 21:55 1722内存是稀缺的资源,哪 ... -
实现下载功能
2010-05-12 10:26 985import java.io.*; import jav ... -
解析JAVA中的内存分配
2010-04-29 08:38 1661照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的 ... -
对象相等性
2010-04-28 21:39 1222String s="hello"; S ... -
Math类和Random的操作
2010-04-27 22:12 1469package javabse; import java.u ... -
日期实体类操作
2010-04-27 21:44 1463package javabse; import java.t ... -
字符串实体类的操作
2010-04-27 21:11 1251package javabse; import java.u ... -
java常用实体类
2010-04-25 22:39 15751.加载文件 System.load(name); Runti ... -
获取环境变量列表
2010-04-25 22:20 1410package javabse; import java.u ... -
取得系统属性列表
2010-04-25 22:08 1401package javabse; import java.u ... -
java浅克隆和深克隆的定义
2010-04-21 17:10 3780深克隆与浅克隆 大家 ... -
java经典问题:传值还是传引用(转过来的)
2010-04-21 17:03 1277经典的问题,但却不容易弄懂,尤其对有c基础的java程序员来说 ...
相关推荐
在掌握了基础和中级概念后,你将进入Java的高级主题,如线程、网络编程、反射以及Java集合框架的深入学习。线程管理是并发编程的关键,而网络编程则让你能够创建可以与其他系统交互的应用。反射允许你在运行时检查和...
### Java新手入门的30个基本概念解析 #### 1. J2SE, J2EE, J2ME:Java的三大平台 Java平台分为三个版本:标准版(J2SE)、企业版(J2EE)和微型版(J2ME)。J2SE是Java的核心平台,适用于桌面应用开发;J2EE主要...
1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...
Java是一种广泛使用的面向对象的编程语言,以其跨平台、高性能和强大的库支持而闻名。这份“java学习入门ppt”提供...这份"java学习入门ppt"将是一个很好的起点,通过它你可以逐步建立起对Java编程和数据库操作的理解。
1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...
### Java新手入门的30个基本概念 #### 1. J2SE、J2EE、J2ME Java平台按照应用场景被分为三个版本:标准版(J2SE)、企业版(J2EE)以及微型版(J2ME)。其中,J2SE是最为基础的Java平台,提供了核心库支持,适合...
孙鑫老师的"JAVA从入门到精通"课程可能涵盖了这些基本概念的深入讲解,通过45.swf、46.swf、47.swf等视频文件,学生可以逐步理解并掌握Java编程的核心知识,包括如何有效地利用Java的包和处理数组。学习过程中,实践...
本章节将深入讲解如何配置Java开发环境以及如何进行反编译操作。Java作为一种广泛应用的编程语言,其开发环境主要包括JDK(Java Development Kit)安装、IDE(集成开发环境)的选择与配置、环境变量设置等。 首先,...
### Java初学者入门概念解析 #### 一、面向对象编程(OOP)基础 面向对象编程(OOP)是Java的核心特性...以上是Java初学者入门所需掌握的一些关键概念和知识点,深入理解这些概念对于编写高质量的Java程序至关重要。
接着,会深入学习Java集合框架,如ArrayList、LinkedList、HashMap和HashSet等,它们是处理数据的重要工具。同时,会探讨线程的使用,理解并发编程的基本原理,学习如何实现线程同步以避免数据竞争问题。 文件名列...
### Java入门所需的30个概念解析 #### 1. Java与C++的比较 ...以上就是Java入门所需的30个核心概念的详细解析,掌握这些概念是学习Java编程的基础,也是进一步深入研究和开发Java应用程序的关键。
- **《Thinking in Java》**:深入理解Java的经典之作。 - **《Head First Java》**:适合初学者的趣味教材。 - **《Effective Java》**:提升Java编程水平的必读之书。 "Java学习网站大全.txt"很可能包含了上述...
标题 "(源码下载)jdk6.0从入门到精通-----chapter2--输入输出,克隆对象" 提供了我们要探讨的主题,即Java中的输入输出流(I/O Stream)和对象克隆。在这个章节中,我们将深入理解这两个关键概念。 **输入输出流...
结合压缩包内的图片和文本文件,这是一个全面的Java开发者入门教程,可以帮助初学者快速进入Java开发领域并理解版本控制的重要性。在实际项目中,掌握这些技能将极大地提升开发效率和团队协作能力。
通过该项目,学习者可以深入了解Flex4.X的核心概念,如MXML和ActionScript的使用、组件设计、数据绑定和事件处理等。 2. **深入学习ExtJs4.1的布局及常用控件** - **知识点**:ExtJs是一款强大的JavaScript库,...
1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...
1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 ...
根据提供的文档信息,我们可以深入探讨Java序列化与反序列化机制以及由此引发的安全漏洞问题。...通过对Java序列化和反序列化机制的深入了解以及对相关安全措施的应用,可以有效降低由反序列化漏洞带来的安全风险。
这一章会深入讲解Servlet和JSP的高级特性,如过滤器、监听器、EL表达式和JSTL标签库。 第六章:MVC设计模式 MVC(Model-View-Controller)模式是Web应用的常见架构,有助于分离业务逻辑、数据模型和用户界面。本...