Java中的Cloneable接口与深拷贝、浅拷贝
Cloneable接口是一个标记接口,也就是没有任何内容,定义如下:
这里分析一下这个接口的用法,clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类的实例上调用clone方法,否则会抛出CloneNotSupportException。Object中默认的实现是一个浅拷贝,也就是表面拷贝,如果需要实现深层次拷贝的话,必须对类中可变域生成新的实例。
Object提供了一个对象拷贝的默认方法clone方法,但是该方法是有缺陷的,它提供了一种浅拷贝方式,也就是它并不会把对象所有属性全部拷贝一份,而是有选择性的拷贝,拷贝规则如下:
1、基本类型
如果变量是基本类型,则拷贝其值,比如:int、float、long等。
2、String字符串
这个比较特殊,拷贝的是地址,是个引用,但是在修改的时候,它会从字符串池(String Pool)中重新生成新的字符串,原有的字符串对象保持不变,此处可以认为String是个基本类型。
3、对象
如果变量时一个实例对象,则拷贝地址引用,也就是说此时新拷贝出的对象与原有对象共享该实例变量,不受访问权限的限制。这在Java中很疯狂,因为它突破了访问权限的定义,一个private修饰的变量,竟然可以被两个实例对象访问。
Cloneable接口如下:如果调用Object的clone方法,没有实现Cloneable接口,则会抛出CloneNotSupportedException
package java.lang; /** * Invoking Object's clone method on an instance that does not implement the
* <code>Cloneable</code> interface results in the exception
* <code>CloneNotSupportedException</code> being thrown.
*
* @author unascribed
* @see java.lang.CloneNotSupportedException
* @see java.lang.Object#clone()
* @since JDK1.0
*/
public interface Cloneable {
}
关于clone方法的浅拷贝的一个demo,可以看出虽然是两个不同的ShallowCopy对象,但是对于他们的非基本数据类型的成员变量是属于同一个引用。因此是浅拷贝
package com.yyrookie.test;
import java.util.Date;
public class ShallowCopy implements Cloneable {
private Date begin;
public Date getBegin(){
return this.begin;
}
public void setBegin(Date d){
this.begin = d;
}
public Object clone(){
Object obj = null;
try{
obj = super.clone();
}catch(CloneNotSupportedException ex){
ex.printStackTrace();
}
return obj;
}
public static void main(String[] args) {
Date date = new Date(10000L);
ShallowCopy copy = new ShallowCopy();
copy.setBegin(date);
ShallowCopy copy2 = (ShallowCopy) copy.clone();
System.out.println(copy.getBegin() + "\n"
+ copy2.getBegin() + "\n" +
(copy == copy2));
date.setTime(100000000L);;
System.out.println(copy.getBegin() + "\n"
+ copy2.getBegin() + "\n" +
(copy == copy2));
}
// Thu Jan 01 08:00:10 CST 1970
// Thu Jan 01 08:00:10 CST 1970
// false
// Fri Jan 02 11:46:40 CST 1970
// Fri Jan 02 11:46:40 CST 1970
// false
}
相比深拷贝,拷贝对象的同时,又进行了对成员对象进行了深拷贝。
package com.yyrookie.test;
import java.util.Date;
public class DeepCopy implements Cloneable{
private Date begin;
public Date getBegin(){
return this.begin;
}
public void setBegin(Date d){
this.begin = d;
}
public Object clone(){
DeepCopy obj = null;
try{
obj = (DeepCopy)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
obj.setBegin((Date)this.getBegin().clone());
return obj;
}
public static void main(String[] args) {
Date date = new Date(10000L);
DeepCopy copy = new DeepCopy();
copy.setBegin(date);
DeepCopy copy2 = (DeepCopy) copy.clone();
System.out.println(copy.getBegin() + "\n"
+ copy2.getBegin() + "\n" +
(copy == copy2));
date.setTime(100000000L);
System.out.println(copy.getBegin() + "\n"
+ copy2.getBegin() + "\n" +
(copy == copy2));
}
// Thu Jan 01 08:00:10 CST 1970
// Thu Jan 01 08:00:10 CST 1970
// false
// Fri Jan 02 11:46:40 CST 1970
// Thu Jan 01 08:00:10 CST 1970
// false
}
Java中的Cloneable接口与深拷贝、浅拷贝的更多相关文章
- Java中的Cloneable接口理解
Cloneable接口是一个标记接口,也就是没有任何内容,定义如下: 这里分析一下这个接口的用法,clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类 ...
- java中的标记接口(标签接口)
Java中的标记接口(Marker Interface),又称标签接口(Tag Interface),具体是不包含任何方法的接口.在Java中很容易找到标记接口的例子,比如JDK中的Serialzab ...
- Java 中的集合接口——List、Set、Map
Java 中的集合接口——List.Set.Map 什么叫集合:集合就是Java API所提供的一系列类的实例,可以用于动态存放多个对象.这跟我们学过的数组差不多,那为什么我们还要学集合,我们看看数组 ...
- 转:二十一、详细解析Java中抽象类和接口的区别
转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...
- 关于JAVA中抽象类和接口的区别辨析
今天主要整理一下新学习的有关于Java中抽象类和接口的相关知识和个人理解. 1 抽象类 用来描述事物的一般状态和行为,然后在其子类中去实现这些状态和行为.也就是说,抽象类中的方法,需要在子类中进行重写 ...
- Java中的Serializable接口和transient关键字
Java中的Serializable接口和transient关键字 Table of Contents 1. 向memcached中放数据时遇到NotSerializableException异常 2 ...
- 用好JAVA中的函数式接口,轻松从通用代码框架中剥离掉业务定制逻辑
大家好,又见面了. 今天我们一起聊一聊JAVA中的函数式接口.那我们首先要知道啥是函数式接口.它和JAVA中普通的接口有啥区别?其实函数式接口也是一个Interface类,是一种比较特殊的接口类,这个 ...
- Java中的Serializable接口transient关键字,及字节、字符、对象IO
1.什么是序列化和反序列化Serialization是一种将对象转为为字节流的过程:deserialization是将字节流恢复为对象的过程. 2.什么情况下需要序列化a)当你想把的内存中的对象保存到 ...
- java中的标记接口
在java 中,RandomAccess和Cloneable .Serializable一样,都是标志性接口,不需要任何实现,只是又来表明其实现类具体有某种特质的,实现了Cloneable表明可以拷贝 ...
随机推荐
- List 与 ArrayList 的使用
最近回顾 java 集合,发现大部分程序中都在使用 List list = new ArrayList(); 也有部分程序使用 ArrayList list = new ArrayList(); 那么 ...
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论. MyBatis将数据缓存设计成两级结构,分为一级缓存 ...
- Java重写父类使用@Override时出现The method destroy() of type xxx must override a superclass method的问题解决
解决方法: 1.把JDK版本改成1.6以上的. 2.把Compiler改成1.6以上的. 关于这两者的区别,参考:http://www.cnblogs.com/EasonJim/p/6741682.h ...
- setState 是异步的
1.解决 setState 异步问题 // 查询 handleSearch(e){ // 禁止默认行为 e.preventDefault(); // 获取 form 表单的值 this.setStat ...
- 关于结构体的具体解说,C、C++中的差别
1. C.C++内置的类型分两种,一种是基本数据类型.一种是复合数据类型.此处我们要讲的结构体便是复合数据类型. 先来讨论一下结构体存在的意义吧.或许你觉得主要的数据类型就够了,为什么还要有结构题这样 ...
- cin,和几个get函数的用法
1.cin.get(字符变量名):用来接收字符 ch = cin.get(); cin.get(ch); 以上两者均可以 2.cin.get(字符数组名,接收字符数目)用来接收一行字符串,可以接收空格 ...
- mysql (primary key)_(unique key)_(index) difference
MYSQL index MYSQL索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找 ...
- Jenkins系列之-—07 集成JIRA
一.Jenkins Jira插件安装&配置 1. 安装插件,主要安装如下插件: Jira Issue Updater 该插件用于更新JIRA ISSUES 的工作流状态或增加备注 JIRA p ...
- oracle死锁解决经常用法(屡试不爽)
--1.查询被锁的情况 select object_name,machine,s.sid,s.serial# from v$locked_object l,dba_objects o ,v$sessi ...
- HDU 2049 不容易系列之(4)——考新郎 (递推,含Cmn公式)
不容易系列之(4)——考新郎 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...