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. TexturePacker压缩png的命令

    压缩png效果最好的当然是TinyPNG这种神器了,不过一般情况下TexturePacker压缩出来的也基本上能达到效果. 你需要先安装TP(TexturePacker的简称,以下TP无特殊说明均指T ...

  2. 搭建windows的solr6服务器(二)

    首先搭建solr环境,如:solr6.0学习(一)环境搭建 修改各种配置文件. 1.修改solrhome下的solr.xml文件 注解掉zookeeper搭建集群配置,我们后面会采用master-sl ...

  3. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  4. Mysql编码, Mysql编码流程, Mysql编码顺序, Mysql编码原理, Mysql编码修改依据

    编码查看方式以及解释说明: 需要以root用户身份登陆才可以查看数据库编码方式(以root用户身份登陆的命令为:>mysql -u root –p,之后两次输入root用户的密码),查看数据库的 ...

  5. Codeforces Round #382 (Div. 2) D. Taxes 哥德巴赫猜想

    D. Taxes 题目链接 http://codeforces.com/contest/735/problem/D 题面 Mr. Funt now lives in a country with a ...

  6. javascript - 二叉树

    都是些简单的东西,所以直接上代码了. /** * Created by huangjacky on 14-10-3. */ function Node(element, left, right) { ...

  7. git的一些相关知识

    1.配置多个git远程仓库的ssh-Key切换(转自) 目前的git仓库如github都是通过使用SSH与客户端连接,如果只是固定使用单个git仓库的单个用户 (first),生成生成密钥对后,将公钥 ...

  8. (转)Python rsa 签名与验证 sign and verify

    转自:http://wawehi.blog.163.com/blog/static/143780306201371361120515/ 网上一搜一大把的 python rsa 相关的东西,python ...

  9. javascript 搜索二叉树

    function Tree() { this.root = null; } Tree.prototype = { constructor: Tree, addItem: function(value) ...

  10. C#集合-列举(Enumeration)

    在计算机这个范畴内存在许多种类的集合,从简单的数据结构比如数组.链表,到复杂的数据结构比如红黑树,哈希表.尽管这些数据结构的内部实现和外部特征大相径庭,但是遍历集合的内容确是一个共同的需求..NET ...