深拷贝浅拷贝
来源:互联网 发布:规模经济 知乎 编辑:程序博客网 时间:2024/06/03 11:56
好久没写东西了,今天来聊聊深浅拷贝这两个东西。
深拷贝浅拷贝,其实我们也叫他深克隆浅克隆,
故名思议就是跟Object基类的clone()有关。
我们先定义一下材料类:
package test;/** * @author lujw E-mail: lujw@toone.com.cn * @date 创建时间:2017年12月11日 下午1:28:33 */public class Material { private String id = "1"; public String getId() { return id; }}
package test;/** * @author lujw E-mail: lujw@toone.com.cn * @date 创建时间:2017年11月16日 下午1:44:30 */public class temp1 { public static void main(String[] args) { Material material = new Material(); Material materialTemp = material; System.out.println(material.toString() + "\n" + materialTemp.toString()); } }
那么,待会出来的结果会是什么呢?相信你们也是知道的,打印了这两个对象实例的地址:
test.Material@7150bd4dtest.Material@7150bd4d
一样的,其实不难知道,这种操作只能是把两个引用引导到堆里面同一块地方。
那么这么样才能"制造出长得一样的实例"呢?这是Object中的clone()就出现了。
要用clone()方法就必须继承Cloneable接口,那为什么clone()是在Object而不是在Cloneable下呢?
其实大家都知道,基本所有的类都基本默认继承了Object,同时clone也应该是所有类的一个基本属性,就写在了Object之下,
如果你没有接上Cloneable这个接口直接用clone()的话,会报CloneNotSupportedException这个异常,这个接口说实在的就是个标志,就是跟你说我是可以克隆的。
-------------------------扯远了----------------------------
那我们接上Cloneable看看
package test;/** * @author lujw E-mail: lujw@toone.com.cn * @date 创建时间:2017年12月11日 下午1:28:33 */public class Material implements Cloneable{ private String id = "1"; public String getId() { return id; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
这里接上Cloneable同时还是重写Object的clone(),不然不给用。
然后我们再改我们的测试main:
package test;/** * @author lujw E-mail: lujw@toone.com.cn * @date 创建时间:2017年11月16日 下午1:44:30 */public class temp1 { public static void main(String[] args) { Material material = new Material(); Material materialTemp = null; try { materialTemp = (Material) material.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } System.out.println(material.toString() + "\n" + materialTemp.toString()); }}
这个时候打印出来的是这样的:
test.Material@6bbc4459test.Material@152b6651这样就实现了对象实例化的克隆。
那有人就问了:废话说得这么多,要讲深克隆浅克隆了吗?
这位兄弟,别急吗,我这就讲,你先把刀从我脖子移开行吗?
浅拷贝:
上面的基础例子我们知道了,那真就是拷贝完成了吗
那我们再来测试一下:
package test;/** * @author lujw E-mail: lujw@toone.com.cn * @date 创建时间:2017年11月16日 下午1:44:30 */public class temp1 { public static void main(String[] args) { Material material = new Material(); Material materialTemp = null; try { materialTemp = (Material) material.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } System.out.println(material.toString() + "\n" + materialTemp.toString()); System.out.println(material.getId().hashCode() + "\n" + materialTemp.getId().hashCode()); //基本类型咱们用hashCode代替。 }}
那你觉得现在结果是怎么样的呢?
答案是这样的:
test.Material@152b6651test.Material@544a5ab24949
材料类(Material)确实是进行了克隆,但是,材料类的里面属性还是在内存的同一块地方啊
这就是浅拷贝了
浅拷贝就是只是克隆了表面而已,但是里面的对象实例内存的指向就还是一样,这个时候我们再来看看我们的深拷贝。
深拷贝:
我们在材料类再加个东西
我们先定义金属类(Metal)
package test;/** * @author lujw E-mail: lujw@toone.com.cn * @date 创建时间:2017年12月12日 下午12:51:39 */public class Metal{ private String id; public String getId() { return id; } public void setId(String id) { this.id = id; }}然后在材料类中加上去这个金属类:
package test;/** * @author lujw E-mail: lujw@toone.com.cn * @date 创建时间:2017年12月11日 下午1:28:33 */public class Material implements Cloneable{ private String id = "1"; private Metal metal = new Metal(); public String getId() { return id; } public Metal getMetal(){ return metal; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
这个时候打印这个
System.out.println(material.getMetal().toString() + "\n" + materialTemp.getMetal().toString());
结果肯定是一样的:
test.Metal@5d888759test.Metal@5d888759
深拷贝的主要点就在这了:
这个时候我们要先给金属类接上Cloneable并加上clone的属性
package test;/** * @author lujw E-mail: lujw@toone.com.cn * @date 创建时间:2017年12月12日 下午12:51:39 */public class Metal implements Cloneable{ private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
@Override protected Object clone() throws CloneNotSupportedException { Material newMaterial = (Material) super.clone(); newMaterial.metal = (Metal) metal.clone(); return newMaterial; }再次测试:
System.out.println(material.toString() + "\n" + materialTemp.toString()); System.out.println(material.getMetal().toString() + "\n" + materialTemp.getMetal().toString());
结果是这样的:
test.Material@152b6651test.Material@544a5ab2test.Metal@5d888759test.Metal@2e6e1408
当然,深拷贝这个东西是没有个绝对的,毕竟每个业务对象是不一样的,每个对象里面的属性是各不相同,
例子我刚刚的材料类(Material),里面有金属类(Metal),那金属类(Metal)之后还有可能是有黄金类(Gold)。。。
所以,复杂的业务往往比较难以全面考虑,全面考虑也是没什么用的,只要紧跟着业务走,就够了,没必要搞什么彻底深拷贝。
----------------------------------------分割线--------------------------------------------------
利用午休写的,写得烂有问题尽管在低下批评。
反正我也不会改。
- 深拷贝&&浅拷贝
- 深拷贝||浅拷贝
- 浅拷贝,深拷贝
- 浅拷贝,深拷贝
- 深拷贝,浅拷贝
- 浅拷贝 深拷贝
- 浅拷贝.深拷贝
- 浅拷贝 深拷贝
- 深拷贝,浅拷贝
- 深拷贝、浅拷贝
- 深拷贝、浅拷贝
- 深拷贝+浅拷贝
- 深拷贝 浅拷贝
- 浅拷贝、深拷贝
- 浅拷贝、深拷贝
- 深拷贝、浅拷贝
- 深拷贝,浅拷贝
- 深拷贝、浅拷贝
- 线程池的参数讲解
- 时间复杂度和空间复杂度的计算
- Bootstrap fileinput 不显示中文解决办法
- 【VR9项目】天马屏配置流程
- 类模版
- 深拷贝浅拷贝
- 基于Node.js的后端应用简介
- 项目设计工具——EA使用教程
- mysql 检测从库状态
- 这是我的第一个博文
- Weex 的 iPhone X 适配
- PLSQL developer远程连接Oracle
- 不懂用户,怎么做新媒体运营
- 年底知识「大甩卖」,知识付费这杯羹还有的分吗?