博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java对象的深浅clone
阅读量:6045 次
发布时间:2019-06-20

本文共 2818 字,大约阅读时间需要 9 分钟。

在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。

浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制,下面将对两者进行详细介绍。

浅clone:

在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

示意如下图:

 

Object类中的native clone方法提供了浅clone的支持。可以实现Cloneable接口并调用Object的clone方法为一个类实现浅clone:

public static void main(String[] args) throws CloneNotSupportedException {        Foo f1 = new Foo(1, new Bar(0));        Foo f2 = f1.clone();        System.out.println(f1);        System.out.println(f2);        f1.id = 2;        f1.bar.setId(2);        System.out.println(f1);        System.out.println(f2);    }    public static class Foo implements Cloneable {        private int id;        private Bar bar;        public Foo(int id, Bar bar) {            this.id = id;            this.bar = bar;        }        @Override        public Foo clone() throws CloneNotSupportedException {            return (Foo) super.clone();        }        @Override        public String toString() {            return "Foo{" +                    "id=" + id +                    ", bar=" + bar +                    '}';        }    }    public static class Bar implements Cloneable {        private int id;        public Bar(int id) {            this.id = id;        }        public void setId(int id) {            this.id = id;        }        @Override        public String toString() {            return "Bar{" +                    "id=" + id +                    '}';        }    }

程序的执行结果如下:

 

在示例程序中改变了f1的引用变量成员bar的值,f2的成员变量bar也受到了影响。不过改变了f1的直接类型成员id的值,f2却没有受影响。

可知:浅clone只能clone成员变量中直接类型的值,对于应用类型的值则是clone了引用对象的地址。

深clone:

在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。

示意如下图:

 

要让我们上面的程序支持深clone,需要对其做些调整:

首先需要给Bar类也添加clone方法的支持:

public static class Bar implements Cloneable {        private int id;        public Bar(int id) {            this.id = id;        }        public void setId(int id) {            this.id = id;        }        @Override        public String toString() {            return "Bar{" +                    "id=" + id +                    '}';        }        @Override        public Bar clone() throws CloneNotSupportedException {            return (Bar) super.clone();        }    }

而后修改Foo类的clone方法:

@Override        public Foo clone() throws CloneNotSupportedException {            Foo f = (Foo) super.clone();            f.bar = bar.clone();            return f;        }

执行结果如下:

Foo{
id=1, bar=Bar{
id=0}}Foo{
id=1, bar=Bar{
id=0}}Foo{
id=2, bar=Bar{
id=2}}Foo{
id=1, bar=Bar{
id=0}}

此时f2不再受到f1的影响了。

此时再继续想一下,如果Bar中还有引用类型成员呢,如果Bar中的引用类型成员也有自己的引用类型成员,那么该怎么办呢?

挺好解决的事情,懒得解释了。

转载于:https://www.cnblogs.com/amunote/p/10217472.html

你可能感兴趣的文章
iOS融云使用原理篇
查看>>
第六章
查看>>
golang+es 爬取网易云音乐评论
查看>>
Math Constants
查看>>
Ajax.BeginForm的异步提交数据 简介
查看>>
Oracle 11g不能导出空表的三种解决方法
查看>>
Wordpress 文章添加副标题
查看>>
21 段实用便捷的 PHP 代码
查看>>
包子凑数
查看>>
CocosStudio文件解析工具CsdAnalysis
查看>>
python 网络通信编程之tcp套接字socket
查看>>
Sql语句批量更新数据(多表关联)
查看>>
设置密码到期的天数
查看>>
Matlab M文件“程序块”注释方法
查看>>
当当网首页——html代码
查看>>
使用JDBCTemplate实现与Spring结合,方法公用 ——共用实现类(BaseImpl)
查看>>
asp.net mvc 实战化项目之三板斧
查看>>
使用stream类型的Result实现Ajax
查看>>
2012,C++,学,还是不学?
查看>>
HDOJ1002
查看>>