美文网首页
java之深拷贝和浅拷贝

java之深拷贝和浅拷贝

作者: 无量散人 | 来源:发表于2018-04-19 16:33 被阅读11次

一、Object类的clone方法

1、说明

Object类的clone方法是native方法

什么是Native Method?简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C/C++语言

2、代码

protected native Object clone() throws CloneNotSupportedException;

二、利用系列化发序列化的clone方法

1、说明

被克隆的对象需要继承Serializable接口

2、代码

import java.io.*;

/**
 * 深度clone工具类,被clone的类必须是序列化了,否则会报错
 * 利用对象的序列化、反序列化达到深度clone
 */
public class CloneUtil {
    public static <T extends Serializable> T clone(T obj) {

        T clonedObj = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);
            oos.close();

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            clonedObj = (T) ois.readObject();
            ois.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return clonedObj;
    }
}

三、实验对比

1、类对象

public class Identity implements Serializable {

    private static final long serialVersionUID = 4980693168901248332L;

    private String idNo;

    private List<String> schoolingNames;

    private Integer age;

    public String getIdNo() {
        return idNo;
    }

    public void setIdNo(String idNo) {
        this.idNo = idNo;
    }

    public List<String> getSchoolingNames() {
        return schoolingNames;
    }

    public void setSchoolingNames(List<String> schoolingNames) {
        this.schoolingNames = schoolingNames;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
public class User implements Serializable, Cloneable{

    private static final long serialVersionUID = 1835115164855723296L;

    private String userName;
    private String password;

    private Identity identity;


    @Override
    public Object clone() throws CloneNotSupportedException{
        return super.clone();
    }

    public Identity getIdentity() {
        return identity;
    }

    public void setIdentity(Identity identity) {
        this.identity = identity;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

2、 测试代码

public class CloneTest {

    public static void main(String[] args) {
        try {
            test1();

            System.out.println("======================");

            test2();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }


    private static void test1() throws CloneNotSupportedException {
        long start = System.currentTimeMillis();

        // 封装user1
        Identity identity = new Identity();
        identity.setAge(10);
        identity.setIdNo("00000000000000");

        List<String> schoolNames = new ArrayList<>();
        schoolNames.add("家里蹲大学");
        identity.setSchoolingNames(schoolNames);

        User user1 = new User();
        user1.setUserName("wangteng");
        user1.setPassword("123456");
        user1.setIdentity(identity);

        // 利用Object的原生clone()方法clone一个对象user2
        User user2 = (User) user1.clone();

        // 比较user1和user2的引用
        boolean result1 = user1==user2;
        System.out.println("user1 == user2 : " + result1);

        // 比较user1和user2的简单类型的属性password属性(String类型,比较特殊点)
        boolean result2 = user1.getPassword()==user2.getPassword();
        System.out.println("user1.getPassword() == user2.getPassword() : " + result2);

        // 比较user1和user2的复杂类型的属性identity属性
        boolean result3 = user1.getIdentity()==user2.getIdentity();
        System.out.println("user1.getIdentity() == user2.getIdentity() : " + result3);

        System.out.println("花费时间:" + (System.currentTimeMillis()-start) + "ms");
    }


    private static void test2() throws CloneNotSupportedException {
        long start = System.currentTimeMillis();

        // 封装user1
        Identity identity = new Identity();
        identity.setAge(10);
        identity.setIdNo("00000000000000");

        List<String> schoolNames = new ArrayList<>();
        schoolNames.add("家里蹲大学");
        identity.setSchoolingNames(schoolNames);

        User user1 = new User();
        user1.setUserName("wangteng");
        user1.setPassword("123456");
        user1.setIdentity(identity);

        // 利用对象的序列化、反序列化达到深度clone
        User user2 = CloneUtil.clone(user1);

        // 比较user1和user2的引用
        boolean result1 = user1==user2;
        System.out.println("user1 == user2 : " + result1);

        // 比较user1和user2的简单类型的属性password属性(String类型,比较特殊点)
        boolean result2 = user1.getPassword()==user2.getPassword();
        System.out.println("user1.getPassword() == user2.getPassword() : " + result2);

        // 比较user1和user2的复杂类型的属性identity属性
        boolean result3 = user1.getIdentity()==user2.getIdentity();
        System.out.println("user1.getIdentity() == user2.getIdentity() : " + result3);

        System.out.println("花费时间:" + (System.currentTimeMillis()-start) + "ms");
    }

}

3、输出

user1 == user2 : false
user1.getPassword() == user2.getPassword() : true
user1.getIdentity() == user2.getIdentity() : true
花费时间:3ms
======================
user1 == user2 : false
user1.getPassword() == user2.getPassword() : false
user1.getIdentity() == user2.getIdentity() : false
花费时间:65ms

四、说明

从上可以看出:
1、Object类的native方法clone()实现的是浅拷贝,序列化反序列化实现的是深拷贝。
2、二者从效率上来看,clone方法由于实现的是浅拷贝同时是native方法,所以效率远远比序列化反序列化的深拷贝来的高。

相关文章

  • java 对象的拷贝

    拷贝:即复制 对象拷贝:即对象复制 java 对象拷贝分类:浅拷贝、深拷贝 java 对象的浅拷贝和深拷贝针对包含...

  • Java基础 - 深拷贝和浅拷贝

    Java 的深拷贝和浅拷贝 什么是深拷贝、浅拷贝 (深克隆、浅克隆)? 在 Java 中,数据类型分为 基本数据类...

  • java中的深拷贝和浅拷贝

    简单记录一下java中的深拷贝和浅拷贝,深拷贝和浅拷贝只是针对对象而言的. 1 深拷贝代码 2 浅拷贝代码 3 测...

  • iOS深拷贝(MutableCopy)与浅拷贝(Copy)的区别

    深拷贝和浅拷贝的概念 iOS中有深拷贝和浅拷贝的概念,那么何为深拷贝何为浅拷贝呢?浅拷贝:浅拷贝并不拷贝对象本身,...

  • Java------List的深拷贝与浅拷贝

    Java的浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。 浅拷贝(Shallow Copy) ...

  • Objective-C中的浅拷贝和深拷贝

    Objective-C中的浅拷贝和深拷贝IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解iOS ...

  • Java的浅拷贝和深拷贝

    首先需要明白,浅拷贝和深拷贝都是针对一个已有对象的操作。那先来看看浅拷贝和深拷贝的概念。 在 Java 中,除了基...

  • iOS面试题-第二页

    11.深拷贝和浅拷贝的理解. 深拷贝;拷贝的内容. 浅拷贝:拷贝的指针. 深拷贝如: NSMutableDicti...

  • 深克隆--何时是尽头?

    As we all know Java有两种拷贝,浅拷贝和深拷贝,高大上的叫法也叫浅克隆和深克隆。 深克隆有时会碰...

  • iOS - copy 与 mutableCopy

    一说到拷贝,就不得不提浅拷贝和深拷贝。 何谓浅拷贝?何谓深拷贝? 往简单的说: 浅拷贝:拷贝地址。 深拷贝:拷贝内...

网友评论

      本文标题:java之深拷贝和浅拷贝

      本文链接:https://www.haomeiwen.com/subject/bevwkftx.html