Java基础——克隆
1、克隆
假设有一个对象object1,在某处又需要一个跟object1一样的实例object2,这两个对象是绝对独立的,不会因为某一个修改另一个随之改变,这样,我们不能直接将对象objec1t的引用赋予object2,object2=object, 这样两个引用仍然指向的是同一个对象,不是两个对象,所以就需要将object1的属性克隆到object2身上
Java中克隆分为两种,浅克隆和深克隆
2、浅克隆
把原型对象中成员变量为值类型的属性都复制给克隆对象,把原型对象中成员变量为引用类型的引用地址也复制给克隆对象
会复制原型对象,但不会复制它所引用的对象
浅克隆只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化
Object类中的clone()方法就是浅克隆
/**
* Creates and returns a copy of this object. The precise meaning
* of "copy" may depend on the class of the object. The general
* intent is that, for any object {@code x}, the expression:
* <blockquote>
* <pre>
* x.clone() != x</pre></blockquote>
* will be true, and that the expression:
* <blockquote>
* <pre>
* x.clone().getClass() == x.getClass()</pre></blockquote>
* will be {@code true}, but these are not absolute requirements.
* While it is typically the case that:
* <blockquote>
* <pre>
* x.clone().equals(x)</pre></blockquote>
* will be {@code true}, this is not an absolute requirement.
* <p>
* By convention, the returned object should be obtained by calling
* {@code super.clone}. If a class and all of its superclasses (except
* {@code Object}) obey this convention, it will be the case that
* {@code x.clone().getClass() == x.getClass()}.
* <p>
* By convention, the object returned by this method should be independent
* of this object (which is being cloned). To achieve this independence,
* it may be necessary to modify one or more fields of the object returned
* by {@code super.clone} before returning it. Typically, this means
* copying any mutable objects that comprise the internal "deep structure"
* of the object being cloned and replacing the references to these
* objects with references to the copies. If a class contains only
* primitive fields or references to immutable objects, then it is usually
* the case that no fields in the object returned by {@code super.clone}
* need to be modified.
* <p>
* ......
*/
//Object类中的clone()方法
protected native Object clone() throws CloneNotSupportedException;
3、深克隆
将原型对象中的所有类型,无论是值类型还是引用类型,都复制一份给克隆对象,也就是说深克隆会把原型对象和原型对象所引用的对象,都复制一份给克隆对象
深克隆是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变
实现Cloneable接口并重写Object类中的clone()方法或者实现Serializable接口,通过对对象的序列化、反序列化实现克隆和字节流输出,通过这三种方式可以实现深克隆
Cloneable接口没有任何方法,仅是个标志接口(tagging interface),若要具有克隆能力,实现Cloneable接口的类必须重写从Object继承来的clone方法,并调用Object的clone方法(见下面Object#clone的定义),重写后的方法应为public的
//Cloneable 接口源码
public interface Cloneable {
}
//重写clone()方法
class CloneClass implements Cloneable{
public Object clone(){
CloneClass o = null;
try{
o = (CloneClass)super.clone();
CloneClass .setAddress(this.address.clone());//引用克隆类型赋值
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}
}
如果引用类型中海包括引用类型, 要实现多层克隆会很麻烦, 这使用可以使用序列化和反序列化的方式实现对象的深克隆,把对象写到字节流中的过程是序列化的过程, 而把对象从字节流中读出来的过程是反序列化的过程. 由于Java序列化的过程中, 写在流中的是对象的一个拷贝, 而原对象仍然在JVM中
public class A implements Serializable {
private static final long serialVersionUID = "序列化ID"; //显式声明ID
public Outer Aclone() {
Outer outer = null;
try {
// 将对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
// 将流序列化成对象
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
outer = (Outer) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return outer;
}
}
通过字节流实现深克隆:
/**
* 通过字节流实现克隆
*/
static class StreamClone {
public static <T extends Serializable> T clone(People obj) {
T cloneObj = null;
try {
// 写入字节流
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bo);
oos.writeObject(obj);
oos.close();
// 分配内存,写入原始对象,生成新对象
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());//获取上面的输出字节流
ObjectInputStream oi = new ObjectInputStream(bi);
// 返回生成的新对象
cloneObj = (T) oi.readObject();
oi.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
}
Java基础——克隆的更多相关文章
- Java基础--对象的克隆
文章转载自https://www.cnblogs.com/Qian123/p/5710533.html 阅读目录 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 假如说你想复制一 ...
- 最适合作为Java基础面试题之Singleton模式
看似只是最简单的一种设计模式,可细细挖掘,static.synchronized.volatile关键字.内部类.对象克隆.序列化.枚举类型.反射和类加载机制等基础却又不易理解透彻的Java知识纷纷呼 ...
- Java基础常见英语词汇
Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的 ['prəʊɡræmɪŋ]编程 OO: object ...
- 【java基础之jdk源码】Object
最新在整体回归下java基础薄弱环节,以下为自己整理笔记,若有理解错误,请批评指正,谢谢. java.lang.Object为java所有类的基类,所以一般的类都可用重写或直接使用Object下方法, ...
- 【JavaEE】企业面试问题-Java基础
1. Java基础部分 1.1 Java中的方法覆盖(Overwrite)和方法重载(Overloading)是什么意思? 重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的 ...
- Java基础(含思维导图)
很早之前整理的Java基础的一些知识点,思维导图: 1.'别名现象' 对一个对象赋值另一个对象,会指向新的对象引用,赋值前的对象引用会由于不再被引用而被gc回收: 而基本类型则不同.基本类型存储了实际 ...
- Java基础系列-ArrayList
原创文章,转载请标注出处:<Java基础系列-ArrayList> 一.概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. ...
- Java面试准备之Java基础
1.Java 语言的优点 面向对象,平台无关,内存管理,安全性,多线程,Java 是解释型的 2.Java 和 C++的区别 多重继承(java接口多重,类不支持,C++支持) 自动内存管理 预处理功 ...
- Java英文单词Java基础常见英语词汇
Java英文单词Java基础常见英语词汇(共70个) ...
随机推荐
- 初识ABP vNext(6):vue+ABP实现国际化
Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 目录 前言 开始 语言选项 语言切换 注意 最后 前言 上一篇介绍了ABP扩展实体,并且在前端部分新增了身份认证管理和租户管理的菜单,在 ...
- 夜息seo培训内部教程
http://www.wocaoseo.com/thread-268-1-1.html 随着SEO日益正规化,在企业中推行SEO变得越来越重要,在上一文<将SEO整合入整个网站项目>中也有 ...
- 如何解决 iframe 无法触发 clickOutside
注:(1)非原创,来自https://blog.csdn.net/weixin_33985679/article/details/89699215.https://zhuanlan.zhihu.com ...
- python IDE(集成开发环境)——PyCharm的安装
选择PyCharm的原因: 1.很多大佬都推荐,说适合实战操作项目 2.另外是界面可视化不错,颜色很舒服(体验完之后的感觉) 3.PyCharm本身有很多操作快捷键很方便(后续可以记下来常用的,方便自 ...
- Angular 之我见
很久没有写过技术软文了,虽然 Angular 发布已有四年,得到了越来越多人的关注,但是仍然有很多人不分青红皂白的进行诋毁.我打算结合自己的经历从客观的角度说聊一聊我眼中的 Angular. 本人刚做 ...
- 详细分析栈和队列的数据结构的实现过程(Java 实现)
目录 栈和队列的数据结构的实现过程(Java 实现) 栈的数据结构的实现 栈的基础知识回顾 栈的常见应用 基于数组的栈的实现 具体代码设计 基于数组的栈简单的时间复杂度分析 关于栈的一个算法应用:括号 ...
- python笔记-正则表达式
什么是正则表达式: 正则表达式是一个特殊的字符序列,能帮助我们方便的检查一个字符串是否与某种模式匹配(定义往往都很枯燥) 也称之为”模式“,即可用于检查一个给定的字符串是否符合某种模式 举例: 我们定 ...
- vue学习笔记一
vue 颠覆式的开发方式 解疑 为什么要学习vue? 降低项目的复杂度 就业需要 vue难不难? 特别简单 相比于React,vue有什么优势? 前端三大框架:Angular.React.Vue Vu ...
- vue 多代理
多代理就要建立多个axios实例对象 vueconfig devServer: { open: true, host: "localhost", // host: "10 ...
- vue require.context自动化导入
语法: require.context(directory, useSubdirectories = false, regExp = /^.//); directory {String} -读取文件的 ...