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基础——克隆的更多相关文章

  1. Java基础--对象的克隆

    文章转载自https://www.cnblogs.com/Qian123/p/5710533.html 阅读目录 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 假如说你想复制一 ...

  2. 最适合作为Java基础面试题之Singleton模式

    看似只是最简单的一种设计模式,可细细挖掘,static.synchronized.volatile关键字.内部类.对象克隆.序列化.枚举类型.反射和类加载机制等基础却又不易理解透彻的Java知识纷纷呼 ...

  3. Java基础常见英语词汇

    Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的                             ['prəʊɡræmɪŋ]编程 OO: object ...

  4. 【java基础之jdk源码】Object

    最新在整体回归下java基础薄弱环节,以下为自己整理笔记,若有理解错误,请批评指正,谢谢. java.lang.Object为java所有类的基类,所以一般的类都可用重写或直接使用Object下方法, ...

  5. 【JavaEE】企业面试问题-Java基础

    1. Java基础部分   1.1 Java中的方法覆盖(Overwrite)和方法重载(Overloading)是什么意思? 重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的 ...

  6. Java基础(含思维导图)

    很早之前整理的Java基础的一些知识点,思维导图: 1.'别名现象' 对一个对象赋值另一个对象,会指向新的对象引用,赋值前的对象引用会由于不再被引用而被gc回收: 而基本类型则不同.基本类型存储了实际 ...

  7. Java基础系列-ArrayList

    原创文章,转载请标注出处:<Java基础系列-ArrayList> 一.概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. ...

  8. Java面试准备之Java基础

    1.Java 语言的优点 面向对象,平台无关,内存管理,安全性,多线程,Java 是解释型的 2.Java 和 C++的区别 多重继承(java接口多重,类不支持,C++支持) 自动内存管理 预处理功 ...

  9. Java英文单词Java基础常见英语词汇

    Java英文单词Java基础常见英语词汇(共70个)                                                                          ...

随机推荐

  1. Http请求-okhttp3基本用法

    简介 HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽.OkHttp是一个高效的HTTP客户端,它有以下默认特性: 支持HTTP/2,允许所有同一个主 ...

  2. Asp.Net Core Swagger 接口分组(支持接口一对多暴露)

    开始之前,先介绍下swagger常用方法. services.AddSwaggerGen    //添加swagger中间件 c.SwaggerDoc  //配置swagger文档,也就是右上角的下拉 ...

  3. “网络巨轮”BGP的高级装备(增强配置)

    引入 如下图在很多时候,BGP建立对等体的时候,要去建立大量的EBGP和IBGP对等体,IBGP还要全连接,这就给我们带来了大量重复的工作,路由表就会变得很庞大,区域内和区域之间就会很难管理,以下这些 ...

  4. .net core国际化

    1.背景 公司业务遍及全球各地,对应业务系统国际化就是顺理成章的事情.最近就接手了一批新老系统的国际化任务,这里把一些探索经验.案例记录下来.本身改造和探索过程包括.NET MVC的,以及.NET C ...

  5. Android Studio 如何导出和导入自己的常用设置,避免重复制造轮子。加快开发速度

    Android Studio 如何导出和导入自己的常用设置,避免重复制造轮子.加快开发速度 作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 在使用 A ...

  6. 使用Android的硬件缩放技术优化执行效率

    Unity3D研究院之使用Android的硬件缩放技术优化执行效率 http://www.xuanyusong.com/archives/3205 Android中GLSurfaceView在横竖屏切 ...

  7. 算法专题 | 10行代码实现的最短路算法——Bellman-ford与SPFA

    今天是算法数据结构专题的第33篇文章,我们一起来聊聊最短路问题. 最短路问题也属于图论算法之一,解决的是在一张有向图当中点与点之间的最短距离问题.最短路算法有很多,比较常用的有bellman-ford ...

  8. 关于List的remove()方法

    最近遇到一个小问题,我将其简化为下列代码,List的remove()方法在下列颜色注重的代码执行的源码也是不同的~ List<Integer> list=new ArrayList< ...

  9. Python基本

    Python基本规则 1.面向对象的跨平台的编程语言 2.文件类型是.py, 3.一个文件是一个模块module,运行整个文件 4.不支持非英文字符,区分大小写 5.一行是一条语句,多条语句写一行用; ...

  10. Oracle数据库访问客户端 sqldeveloper-19.2.1.247.2212-x64 下载

    Oracle数据库访问客户端 sqldeveloper-19.2.1.247.2212-x64 地址:https://pan.baidu.com/s/1iojCVxwXocyM8oObTf0xaw 这 ...