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. js 日期有效性验证 的一点思考

    在日常项目中经常遇到日期输入验证,以前我遇到的项目是日期只能通过日历控件来选择,最近我同事遇到一个问题是日期除了可以通过日历控件来输入也可以手动来输入,可是我们项目中居然没有日期格式的验证方法(备注: ...

  2. DRAM 内存介绍(二)

    参考资料:http://www.anandtech.com/show/3851/everything-you-always-wanted-to-know-about-sdram-memory-but- ...

  3. 分布式Hadoop安装(二)

    二.集群环境安装Zookeeper 1.         hadoop0,namenode机器下,配置zookeeper,先解压安装包. 使用命令:tar -zxvf zookeeper-3.4.4. ...

  4. bash可改动的环境变量

    环境变量名 变量的用途 CDPATH 包括cd命令要逐个查找的路径,cd命令在这些路径下查找作为參数传递给它的文件夹名.假设CDPATH没有设置,cd命令则查找当前文件夹 EDITOR 用户在程序中使 ...

  5. Linux: Set OR Change The Library Path

    Linux: Set OR Change The Library Path by NIX CRAFT on APRIL 9, 2010 · 3 COMMENTS· LAST UPDATED AUGUS ...

  6. NGUI 减少drawcall规则

    前置说明一: Unity中的drawcall定义: 每次引擎准备数据并通知GPU的过程称为一次Draw Call. Unity(或者说基本所有图形引擎)生成一帧画面的处理过程大致可以这样简化描述:引擎 ...

  7. Scala 深入浅出实战经典 第43讲:主要介绍类型变量bound

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  8. brew 出现 git 错误的问题分析

    现象 brew update的时候出现 gitcrash   分析 在brew update 的时候看见有 git gc 的字样,提示有在gc 的动作.到/usr/local/ 目录,直接运行 git ...

  9. LeetCode: Path Sum II 解题报告

    Path Sum II Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals ...

  10. iOS开发——项目实战总结&Block使用注意点浅析

    Block使用注意点浅析 1.在使用block前需要对block指针做判空处理. 不判空直接使用,一旦指针为空直接产生崩溃. if (!self.isOnlyNet) { if (succBlock ...