java开发——Cloneable接口、clone()方法和深浅拷贝
1、实现Cloneable接口表明该类的对象是允许克隆的。
2、允许克隆的意思是:可以调用clone()方法。
3、深拷贝还是浅拷贝,取决于如何重写Object的clone()方法。
4、原对象和克隆对象的关系:
深拷贝:阳关道和独木桥;
浅拷贝:藕断丝连。
上面的第二点解释一下,如果没有实现Cloneable就调用clone()方法,会抛出异常。看下Object源码就知道了:
- protected Object clone() throws CloneNotSupportedException {
- if (!(this instanceof Cloneable)) {//这里会检查是否是Cloneable的实例
- throw new CloneNotSupportedException(
- "Class " + getClass().getName() +" doesn't implement Cloneable");
- }
- return internalClone();
- }
下面举一个深拷贝的例子:
ArrayList的clone()方法:
- //深拷贝
- public Object clone() {
- try {
- ArrayList<?> v = (ArrayList<?>) super.clone();
- //新开辟一个内存空间给ArrayList的对象成员Object[] elementData;
- v.elementData = Arrays.copyOf(elementData, size);
- v.modCount = 0;
- return v;
- } catch (CloneNotSupportedException e) {
- // this shouldn't happen, since we are Cloneable
- throw new InternalError(e);
- }
- }
- //transient Object[] elementData;
这样得到新的ArrayList对象,则是一个完全独立的对象,包括对象属性成员和原来对象没有任何联系。你走你的阳关道,我走我的独木桥,你以后做什么事都影响不了我。这就是深拷贝。
如果把上面的深拷贝改成浅拷贝,将会变成:
- //浅拷贝
- public Object clone() {
- try {
- ArrayList<?> v = (ArrayList<?>) super.clone();
- //有公用的对象成员elementData,它就是连接两个对象的罪魁祸首。
- v.elementData = elementData;
- v.modCount = 0;
- return v;
- } catch (CloneNotSupportedException e) {
- // this shouldn't happen, since we are Cloneable
- throw new InternalError(e);
- }
- }
- //transient Object[] elementData;
使用上面这个浅拷贝的clone()方法,原对象和克隆对象各自的对象成员elementData指向同一块内存地址,藕断丝连,相互影响着。你受伤了,我就难过;你过的开心,我就默默祝福你;你想我的时候,我也在想你。这就是浅拷贝。
补充:如果A的对象成员属性是自己定义的类型(记为B),A想要深拷贝,需要依靠B的深拷贝clone()方法。
参考书籍:Effective Java(第2版)
java开发——Cloneable接口、clone()方法和深浅拷贝的更多相关文章
- Java的Cloneable接口还有深浅复制
我的小记录 首先语法上,搞清除,Java有个Cloneable接口,但这个接口是没有定义方法的. 那实现了这个接口有什么用呢? 再看Object类中,有个clone()方法,这个方法提供一个浅复制的功 ...
- 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)
编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...
- jQuery开发插件的两个方法 js 深浅拷贝
1.jQuery.extend(object);为扩展jQuery类本身.为类添加新的方法.由全局函数来调用, 主要是用来拓展个全局函数 2.jQuery.fn.extend(object);为jQu ...
- java Object对象的clone方法
参考copy链接:http://blog.csdn.net/bigconvience/article/details/25025561 在看原型模式,发现要用到clone这个方法,以前和朋友聊过,没怎 ...
- Java 中如何使用clone()方法克隆对象?
java为什么要 对象克隆: 在程序开发时,有时可能会遇到以下情况:已经存在一个对象A,现在需要一个与A对象完全相同的B 对象,并对B 对象的属性值进行修改,但是A 对象原有的属性值不能改变.这时,如 ...
- 没想到吧,Java开发 API接口可以不用写 Controller了
本文案例收录在 https://github.com/chengxy-nds/Springboot-Notebook 大家好,我是小富~ 今天介绍我正在用的一款高效敏捷开发工具magic-api,顺便 ...
- java中获取接口(方法)中的参数名字(eclipse设置编译参数)(java8 javac -parameters)
interface接口参数 jdk1.7及以前使用spring功能实现的: 注意: 1.该功能只能获取类的方法的参数名,不能获取接口的方法的参数名. public static void test() ...
- java开发之——[接口回调]
一.回调的含义和用途 1. 什么是回调? 一般来说,模块之间都存在一定的调用关系,从调用方式上看,可以分为三类:同步调用.异步调用和回调.同步调用是一种阻塞式调用,即在函数A的函数体里通过书写函数B的 ...
- 在idea的java开发中字符串length()方法获取长度与赋值不符的问题
最近在开发中用到length()方法获取中文字符串的长度,发现获得的长度与实际不符.比如个String类型赋值为"中",但获取长度却是2. 这让我百思不得其解,后来突然想起来我在研 ...
随机推荐
- 2)header的使用
header() 函数向客户端发送原始的 HTTP 报头. 认识到一点很重要,即必须在任何实际的输出被发送之前调用 header() 函数(在 PHP 以及更高的版本中,您可以使用输出缓存来解决此问题 ...
- F. Moving On
http://codeforces.com/gym/102222/problem/F fory #include<bits/stdc++.h> using namespace std; t ...
- python语法基础-基础-变量和数据类型
############### 第一个python程序 ############### print("hello python") # 打印hello python # 分 ...
- openpyxl传入表名时不要使用默认的sheet表名
openpyxl传入表名时不要使用默认的sheet表名,会报错 处理:改一下表名即可
- 4k高分屏下,chm帮助文档,api文档打开后字体过小的解决
如图所示: 4k分辨率下,chm文件的正文部分的字体过小,这是这些网页可能使用了CSS维持字体dpi, 在普通分辨率下,可以显示正常,但在高分屏下就会显示得过小,这时我们就需要调整显示网页 的显示效果 ...
- react全家桶从0搭建一个完整的react项目(react-router4、redux、redux-saga)
react全家桶从0到1(最新) 本文从零开始,逐步讲解如何用react全家桶搭建一个完整的react项目.文中针对react.webpack.babel.react-route.redux.redu ...
- 吴裕雄--天生自然python编程:实例(3)
# 返回 x 在 arr 中的索引,如果不存在返回 -1 def binarySearch (arr, l, r, x): # 基本判断 if r >= l: mid = int(l + (r ...
- IDEA+Maven+JavaWeb+tomcat项目搭建(图文并茂,详细)
一.创建Maven项目 1:如果刚打开IDEA,显示的是这个页面,我们直接单击 Create New Project(创建项目) 或者 File-> New-> Project 2:选中左 ...
- python字符串复制的几种方法
>>> list1 = [1,2] >>> id(list1) 50081032 >>> list2 = list1.copy() >> ...
- SpringMVC之参数绑定
1.Controller package com.tz.controller; import org.springframework.beans.factory.annotation.Required ...