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表明可以拷贝 ...
随机推荐
- Blazor——Asp.net core的新前端框架
原文:Blazor--Asp.net core的新前端框架 Blazor是微软在Asp.net core 3.0中推出的一个前端MVVM模型,它可以利用Razor页面引擎和C#作为脚本语言来构建WEB ...
- [WASM Rust] Use the js-sys Crate to Invoke Global APIs Available in Any JavaScript Environment
js-sys offers bindings to all the global APIs available in every JavaScript environment as defined b ...
- 适合新人学习的iOS官方Demo
UICatalog.包括了绝大部分经常使用的UI,入门必备良药. 9 分段选择器 10滑动条 Slider 11stack view 12 分步条 13 开关 14 textfield 15text ...
- goang Receiver & interface
package main import ( "fmt" ) type Pointer struct { x string } func (this *Pointer) PrintX ...
- c程序设计语言第一章2
练习1.13编写一个程序,打印输入中单词长度的直方图.水平方向的直方图比较容易绘制,垂直方向的直方图则要困难些 #include <stdio.h> #include <stdlib ...
- Excel实用技巧-如何批量提取excel工作表名称
Excel实用技巧-如何批量提取excel工作表名称 1. 打开Excel文件,点击“公式”栏,进而点击“定义管理器” 2. 在弹出的对话框中,点击新增按钮, 名称:“sheet”,引用位置:“=RE ...
- AVL树,红黑树,B-B+树,Trie树原理和应用
前言:本文章来源于我在知乎上回答的一个问题 AVL树,红黑树,B树,B+树,Trie树都分别应用在哪些现实场景中? 看完后您可能会了解到这些数据结构大致的原理及为什么用在这些场景,文章并不涉及具体操作 ...
- 程序设计之另一种读写函数---writev,readv
read()和write()系统调用每次在文件和进程的地址空间之间传送一块连续的数据.但是,应用有时也需要将分散在内存多处地方的数据连续写到文件中,或者反之.在这种情况下,如果要从文件中读一片连续的数 ...
- EF(Entity Framework)通用DBHelper通用类,增删改查以及列表
其中 通用类名:DBhelper 实体类:UserInfo 1 //新增 2 DBHelper<UserInfo> dbhelper = new DBHelper<UserInfo& ...
- 二阶段 三阶段 提交 Paxos
关于分布式事务.两阶段提交协议.三阶提交协议 - 文章 - 伯乐在线 http://blog.jobbole.com/95632/