栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

clone方法的思考

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

clone方法的思考

事情起因

某个同学希望某个类可被clone,该类其实继承HashMap,本身有clone,但是该同事不知道,所以写了一个clone方法

@Override
    public Object clone() {
        return SerializationUtils.clone(this);
    }

结果他的代码正常,其它地方在clone的时候,报了另外一个类java.io.NotSerializableException

原因分析

1.该类原先继承HashMap,所以原来clone是调用HashMap的clone(value值为浅拷贝)
2.该类的clone方法被同学覆盖,使用的是SerializationUtils.clone(深拷贝)
3.SerializationUtils.clone方法需要类实现Serializable,并且如果其包含的属性非原生数据类型,其属性类也需要实现Serializable

解决方案 解决方案一

如果项目只需要浅拷贝,获取值,而不改变值里面的内容,则可以使用HashMap的clone方法

解决方案二

如果项目需要做深拷贝,可能改变值里面的内容,那么需要重写clone方法,可以SerializationUtils.clone,但是类及其子类都需要实现Serializable接口

总结思考 浅拷贝&深拷贝

浅拷贝:如果基本数据类型则拷贝一份,非基本类型(包括数组)都只是拷贝引用,所以非基本数据类型原始值修改,则拷贝也会修改
深拷贝:无论是否基本数据类型都会做一份拷贝

HashMap的clone

hashmap的拷贝,看代码

public Object clone() {
    HashMap result;
    try {
        result = (HashMap)super.clone();
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
    result.reinitialize();
    result.putMapEntries(this, false);
    return result;
}

HashMap的clone方法,map会生成新的对象,但新的HashMap所存储的引用类型还是原来Map的值,hashmap的clone本身map会复制一份,但是其value值是一个浅拷贝。

浅拷贝实现方式 通过实现Cloneable接口

java实现一个类的浅拷贝,则只需要实现Cloneable接口,同时覆盖重新Objec的clone方法即可

public class MyClass implements Cloneable{
    Integer num;
    MySubClass mySubClass;

    public MyClass(Integer num, MySubClass mySubClass) {
        this.num = num;
        this.mySubClass = mySubClass;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

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

为什么要实现Cloneable接口,这个接口没有任何方法;其实只是打上一个标识,在Object的native clone方法中有一段代码就是判断是否实现该接口。可能是为了表示有些类可以clone,有些类不能clone吧。

通过BeanUtils

使用apache的Common BeanUtils,pom文件引入


    commons-beanutils
    commons-beanutils
    1.9.4

代码如下:

MySubClass mySubClass1 = (MySubClass)BeanUtils.cloneBean(mySubClass);
System.out.println(mySubClass1);

其原理是通过反射创建一个新对象,然后通过copyProperties方法将类的值一个个拷贝,因此是一个浅拷贝

深拷贝实现方式

当然深拷贝有自身实现的方式,比如还是继续重写clone方法,在clone方法中将非基本数据类型new出一个新对象,子对象也是重新clone方法,这样会比较繁琐。这里有些工具类可供选择

Apache Commons Lang序列化方式深拷贝
MyClass myClass = new MyClass();//该类必须实现Serializable接口
SerializationUtils.colne(myClass);

其原理是通序列化和反序列化的方式,重新生成对象。不过需要每个类都实现Serializable接口

Gson或者JackJson序列化方式深拷贝

其原理也差不多,是同步序列化成json对象,再反序列化。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/936604.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号