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接口与深拷贝、浅拷贝的更多相关文章

  1. Java中的Cloneable接口理解

    Cloneable接口是一个标记接口,也就是没有任何内容,定义如下: 这里分析一下这个接口的用法,clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类 ...

  2. java中的标记接口(标签接口)

    Java中的标记接口(Marker Interface),又称标签接口(Tag Interface),具体是不包含任何方法的接口.在Java中很容易找到标记接口的例子,比如JDK中的Serialzab ...

  3. Java 中的集合接口——List、Set、Map

    Java 中的集合接口——List.Set.Map 什么叫集合:集合就是Java API所提供的一系列类的实例,可以用于动态存放多个对象.这跟我们学过的数组差不多,那为什么我们还要学集合,我们看看数组 ...

  4. 转:二十一、详细解析Java中抽象类和接口的区别

    转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...

  5. 关于JAVA中抽象类和接口的区别辨析

    今天主要整理一下新学习的有关于Java中抽象类和接口的相关知识和个人理解. 1 抽象类 用来描述事物的一般状态和行为,然后在其子类中去实现这些状态和行为.也就是说,抽象类中的方法,需要在子类中进行重写 ...

  6. Java中的Serializable接口和transient关键字

    Java中的Serializable接口和transient关键字 Table of Contents 1. 向memcached中放数据时遇到NotSerializableException异常 2 ...

  7. 用好JAVA中的函数式接口,轻松从通用代码框架中剥离掉业务定制逻辑

    大家好,又见面了. 今天我们一起聊一聊JAVA中的函数式接口.那我们首先要知道啥是函数式接口.它和JAVA中普通的接口有啥区别?其实函数式接口也是一个Interface类,是一种比较特殊的接口类,这个 ...

  8. Java中的Serializable接口transient关键字,及字节、字符、对象IO

    1.什么是序列化和反序列化Serialization是一种将对象转为为字节流的过程:deserialization是将字节流恢复为对象的过程. 2.什么情况下需要序列化a)当你想把的内存中的对象保存到 ...

  9. java中的标记接口

    在java 中,RandomAccess和Cloneable .Serializable一样,都是标志性接口,不需要任何实现,只是又来表明其实现类具体有某种特质的,实现了Cloneable表明可以拷贝 ...

随机推荐

  1. Linux下文件操作命令cat(转)

    语法格式: cat [-AbeEnstTuv] [--help] [--version] fileName 参数说明: -n 或 --number:由 1 开始对所有输出的行数编号. -b 或 --n ...

  2. Java屏幕截图工具 捕获屏幕

    原文:http://www.open-open.com/code/view/1420037709781 import java.awt.BorderLayout; import java.awt.Co ...

  3. 超级强大的淘宝开源平台(taobao-code)

    今天发现了一个免费又高级的开源SVN服务器,taobao,阿里云CODE.迫不及待的注册了一个.感觉不错,分享给大家. 先说说我们用过的几个SVN服务器吧: google code oksvn(感觉不 ...

  4. 【Android开发—智能家居系列】(一):智能家居原理

    来到JCZB公司的第二天,就接到了开发类似于小米智能家庭APP的任务.组长让我在手机上安装上此款APP,给了我个小米智能插座,就让我开始了解需求.这便开启了我的智能家居旅程.说实话,我也真是out的无 ...

  5. 大话大前端时代(一) —— Vue 与 iOS 的组件化

    序 今年大前端的概念一而再再而三的被提及,那么大前端时代究竟是什么呢?大前端这个词最早是因为在阿里内部有很多前端开发人员既写前端又写 Java 的 Velocity 模板而得来,不过现在大前端的范围已 ...

  6. 转:某运维DBA的mysql学习心得

    转自:http://www.cnblogs.com/lyhabc/p/3691555.html 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心 ...

  7. INAPP

    1. Login API : 接口為您提供了我們的登入服務,可以讓使用者透過facebook帳號登入我們的服務,在您呼叫此API後,可以得到 使用者的UUID(Unique UID為使用者在平台的唯一 ...

  8. MYSQL强制使用索引和禁止使用索引

    mysql强制索引和禁止某个索引 1.mysql强制使用索引:force index(索引名或者主键PRI) 例如: select * from table force index(PRI) limi ...

  9. HDU 6058 Kanade's sum 二分,链表

    Kanade's sum Problem Description Give you an array A[1..n]of length n. Let f(l,r,k) be the k-th larg ...

  10. 如何设计一个优秀的API

    如何设计一个优秀的API - 文章 - 伯乐在线 http://blog.jobbole.com/42317/ 如何设计一个优秀的API - 标点符 https://www.biaodianfu.co ...