Java中对象的赋值分为浅拷贝和深拷贝

1.对象浅拷贝

public class CloneTest{
    static class Emp{
        String name;
        int age;
        Date hireDate;
    }
    public static void main(String[] args){
        Emp emp1=new Emp();
        Emp emp2=emp1;
    }
}

这种用“=”赋值的情况下就是对象的浅拷贝。在内存中emp1和emp2都指向java堆中同一个对象(如果虚拟机让引用直接存储的是对象的地址的话就指向同一块内存地址,如果引用存储的是一个句柄的话,就指向同一个句柄)。

在这种情况下,无论我们修改的是emp1还是修改emp2都会在另一个引用中表现出来。可是在通常情况下我们想得到这样的一个对象:和原来对象一样但又不是同一个。这是我们就得使用对象克隆。

2.对象深拷贝

2.1对象克隆

一个对象能被克隆的前提是它必须继承Cloneable接口。该接口没有包含任何内容只是一个标记,表示该类的所有对象可以被克隆。然后使用public修饰符重新定义clone方法,因为,clone方法在Object类中被定义为protected,它默认也是浅拷贝。

protected native Object clone() throws CloneNotSupportedException;

在覆写该clone方法时可以使用协变技术让clone类返回特定的类型。

public class Emp implements Cloneable{
    private String name;
    private int age;
    private Date hireDate;    

    @Override
    protected Emp clone() throws CloneNotSupportedException {
        Emp emp =(Emp)super.clone();
        emp.hireDate=(Date)hireDate.clone();
        return emp;
    }
}

在这里我们看到,Date类可以调用clone方法没有出错是因为Date类继承了Cloneable接口。

public class Date implements java.io.Serializable, Cloneable, Comparable<Date>

但是当我们类中使用的一个组件它并没有继承Cloneable接口时我们该怎么办?还有一个问题是使用clone方法就得是与该对象有关的对象链上的所有对象都继承Cloneable接口。这未免有些太麻烦,况且一个类在设计的时候不知道他是否要被克隆,难道当你需要克隆的时候通知那个类的程序员让他给类添加Cloneable继承?这显然是不合理的。因此,这种使用clone方法实现对象的深拷贝不建议使用

2.2对象序列化方式实现深拷贝

关于对象序列化请移步这里。

只要对应的类是可序列化的即可。其做法很简单:直接将对象序列化到输出流中,然后将其读回。这样产生的新对象是对现有对象的一个深拷贝。在此过程中,我们不必将对象写出到文件中,因为可以用ByteArrayOutputStream将数据保存到字节数组中。

public class SerialCloneable implements Cloneable,Serializable {
    private static final long serialVersionUID = 7403553044775279221L;
    public Object clone() {
        try {
            //save the object to a byte array
            ByteArrayOutputStream bout=new ByteArrayOutputStream();
            ObjectOutputStream out= new ObjectOutputStream(bout);
            out.writeObject(this);
            out.close();
            // read clone of the object from the byte array
            ByteArrayInputStream bin= new ByteArrayInputStream(bout.toByteArray());
            ObjectInputStream in=new ObjectInputStream(bin);
            Object ret=in.readObject();
            in.close();
            return ret;
        } catch (Exception e) {
            return null;
        }
    }
}

更简单的方法,想要得到clone,只需要扩展SerialCloneable类,这样就完事了。但是应当慎用,因为它通常会比显示地构建对象并复制或克隆数据域的克隆方法慢得多。

Java对象的复制的更多相关文章

  1. java对象深复制、浅复制(深拷贝、浅拷贝)的理解

    先看一个例子 User user1 = new User(); user1.setId("111"); Map<String, User> map1 = new Has ...

  2. Java——对象的复制、克隆、序列化

    原创作者: https://blog.csdn.net/lmb55/article/details/78277878对象克隆(复制)假如说你想复制一个简单变量.很简单: int apples = 5; ...

  3. java对象克隆复制

    原文链接:https://blog.csdn.net/ztchun/article/details/79110096 自己先简单描述总结一下:当想要将一个对象中已有的值直接给另外一个对象的时候,其实并 ...

  4. java 对象属性复制,将一个对象的属性值赋值给另一个对象, 属性名需要相同

    import org.springframework.beans.BeanUtils; BeanUtils.copyProperties(源对象, 目标对象);

  5. JAVA对象转换JSON

    1. 把java 对象列表转换为json对象数组,并转为字符串 复制代码 代码如下: JSONArray array = JSONArray.fromObject(userlist); String ...

  6. Java 对象复制

    Java 对象的一共有 3 种复制对象的方式. 1.直接赋值 (引用复制 ),此种复制方式比较常用. 诸如 A  a = b ;  a 是直接复制了b的引用 ,也就是说它俩指向的是同一个对象. 此时 ...

  7. Java学习笔记之对象的复制和克隆

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

  8. Java对象和集合的拷贝/克隆/复制

    昨天同事遇到了一个奇怪的问题,他需要将一个JavaBean拷贝一份,然后对新创建的Bean进行操作.但是他对新的Bean操作后,会影响旧的Bean的值.当听到这个问题的时候,我第一反应就是他的拷贝方法 ...

  9. java复制对象,复制对象属性,只可复制两个对象想同的属性名。也可自定义只复制需要的属性。

    注意:使用时copy()方法只会复制相同的属性.常用的copy()方法.以下为封装的工具和使用方式. 1.封装类 import java.util.Map; import java.util.Weak ...

随机推荐

  1. Revit中如何添加水平仰视平面视图

    在Revit平面视图中视角是俯视视角,但是在一些特殊的情况下,我们可能需要创建仰视视角的平面视图,例如我们需要向上看天花板的灯具布置的时候,下面举例说明添加仰视平面视图的方法. 如图在模型中有一楼板跟 ...

  2. VB中WinSock控件的属性、方法、事件及应用

    一.WinSock简介       Socket(套接字)最初是由加利福尼亚大学Berkeley(伯克利)分校为UNIX操作系统开发的网络通信接口,随着UNIX的广泛使用,Socket成为当前最流行的 ...

  3. 关于ORACLE的重启命令

    有时候数据死了,或者没有监听,不必重启机子,重启一下数据库服务行了,下面是linux下的启动步骤,没有在win下执行过,可能也可以!以oracle9i为例(1) 以oracle身份登录数据库,命令:s ...

  4. 设置360调用样式 IE调用样式

    <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding= ...

  5. 通过Typings为Visual Studio Code增强智能提示功能

    缘起 最近在学习Node.js及ThinkJS这个框架,用vscode作为开发环境.默认情况下vscode对ThinkJS的代码提示并不好,所以研究了一下,原来可以同通过Typings来让vscode ...

  6. 【LeetCode】264. Ugly Number II

    Ugly Number II Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose ...

  7. Git + BeyondCompare

    Mac 环境: 1. 安装 BeyondCompare 2. 配置 ~/.gitconfig [diff] tool = bcomp [merge] tool = bcomp [difftool &q ...

  8. 使用Fragment应用放置后台很久,被系统回收,出现crash

    使用Fragment应用放置后台很久,被系统回收,出现crash:原因:系统做了源码FragmentActivity调用onSaveInstanceState保存Fragment对象,这时候系统恢复保 ...

  9. 即将放出ITSEC第一期所有培训视频

    课程大概被分为三个章节 客户端安全培训 安全工具培训 服务端安全培训   部分PPT                         详细课程表 FireBug代码调试工具使用:工具介绍 FireBu ...

  10. CLR VIA

     标题  状态  内容 什么是CLR? 什么是托管模块? 托管模块由什么组成? .net代码的执行过程   http://www.cnblogs.com/aaa6818162/p/4726581.ht ...