java浅拷贝和深拷贝(基础也是很重要的)
对象的copy你兴许只是懵懂,或者是并没在意,来了解下吧。
对于的github基础代码https://github.com/chywx/JavaSE
最近学习c++,跟java很是相像,在慕课网学习c++也算是重温习了下java基础
明白了当初讲师一直强调java传递的话只有值传递,不存在引用传递,为什么一直要重复这,既然只有值传递,为啥还强调不是引用传递
毛病啊这是
学了c++才知道,原来c++有值传递,引用传递的说法,但是java只是值传递
最简单的理解就是对于方法调用
比如 f(int a,int b) 这是值传递,传递过来的值不会被修改。
再如 f(int &a,int &b)这是引用传递,传递过来的值会被修改
步入正轨,说一说java的浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。
浅拷贝(Shallow Copy):①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
通过示例来了解下,
一:
使用构造函数实现copy
- public class Person {
- public static void main(String[] args) {
- Son s = new Son(10);
- Person p1 = new Person("大海", s);
- Person p2 = new Person(p1);
- p1.setSonName("小海");
- p1.getSon().setAge(12);
- System.out.println("p1:" + p1);// p1:Person [sonName=小海, son=Son [age=10]]
- System.out.println("p2:" + p2);// p2:Person [sonName=大海, son=Son [age=10]]
- }
- private String sonName;
- private Son son;
- // 自定义拷贝函数
- public Person(Person person) {
- this.sonName = person.sonName;
- this.son = person.son;
- }
- public Person(String sonName, Son son) {
- super();
- this.sonName = sonName;
- this.son = son;
- }
- public String getSonName() {
- return sonName;
- }
- public void setSonName(String sonName) {
- this.sonName = sonName;
- }
- public Son getSon() {
- return son;
- }
- public void setSon(Son son) {
- this.son = son;
- }
- @Override
- public String toString() {
- return "Person [sonName=" + sonName + ", son=" + son + "]";
- }
- }
- class Son {
- private int age;
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public Son(int age) {
- super();
- this.age = age;
- }
- @Override
- public String toString() {
- return "Son [age=" + age + "]";
- }
- }
结果
p1:Person [sonName=小海, son=Son [age=12]]
p2:Person [sonName=大海, son=Son [age=12]]
对于上面的实例,该person对象有两个成员,一个基本类型,一个引用类型,结果是拷贝出来的对象,基本类型的那个成员真正的实现了copy。
二:
使用自带的clone方法,需要实现cloneable接口,不然会
Exception in thread "main" java.lang.CloneNotSupportedException:
- public class Person2 implements Cloneable {
- public static void main(String[] args) throws CloneNotSupportedException {
- Son2 son1 = new Son2(10);
- Person2 person1 = new Person2("大海", son1);
- Person2 person2 = (Person2) person1.clone();
- person2.setSon2Name("小海");
- person2.getSon2().setAge(12);
- System.out.println(person1);
- System.out.println(person2);
- }
- public Person2(String son2Name, Son2 son2) {
- super();
- this.son2Name = son2Name;
- this.son2 = son2;
- }
- private String son2Name;
- private Son2 son2;
- public String getSon2Name() {
- return son2Name;
- }
- public void setSon2Name(String son2Name) {
- this.son2Name = son2Name;
- }
- public Son2 getSon2() {
- return son2;
- }
- public void setSon2(Son2 son2) {
- this.son2 = son2;
- }
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- @Override
- public String toString() {
- return "Person2 [son2Name=" + son2Name + ", son2=" + son2 + "]";
- }
- }
- class Son2 {
- private int age;
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- @Override
- public String toString() {
- return "Son2 [age=" + age + "]";
- }
- public Son2(int age) {
- super();
- this.age = age;
- }
- }
结果:
Person2 [son2Name=大海, son2=Son2 [age=12]]
Person2 [son2Name=小海, son2=Son2 [age=12]]
使用自带的copy实现浅拷贝
---------------------------------------------------------------------------------------------------
深拷贝
相对于浅拷贝而言,对于引用类型的修改,并不会影响到对应的copy对象的值。每一层的每个对象都进行浅拷贝=深拷贝。
一:
还是使用clone方法,只不过得手动重写一下。
上代码
- public class Person3 implements Cloneable {
- public static void main(String[] args) throws CloneNotSupportedException {
- Son3 son1 = new Son3(10);
- Person3 person1 = new Person3("大海", son1);
- Person3 person2 = (Person3) person1.clone();
- person2.setSon2Name("小海");
- person2.getSon3().setAge(12);//修改对应的引用对象的值。
- System.out.println(person1);
- System.out.println(person2);
- }
- public Person3(String son2Name, Son3 son3) {
- super();
- this.son2Name = son2Name;
- this.son3 = son3;
- }
- private String son2Name;
- private Son3 son3;
- public String getSon2Name() {
- return son2Name;
- }
- public void setSon2Name(String son2Name) {
- this.son2Name = son2Name;
- }
- public Son3 getSon3() {
- return son3;
- }
- public void setSon3(Son3 son3) {
- this.son3 = son3;
- }
- @Override
- protected Object clone() throws CloneNotSupportedException {
- Person3 clone = (Person3) super.clone();
- clone.setSon3((Son3) clone.getSon3().clone());
- return clone;
- }
- @Override
- public String toString() {
- return "Person3 [son2Name=" + son2Name + ", son3=" + son3 + "]";
- }
- }
- class Son3 implements Cloneable {
- private int age;
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- @Override
- public String toString() {
- return "Son2 [age=" + age + "]";
- }
- public Son3(int age) {
- super();
- this.age = age;
- }
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- }
结果:
Person3 [son2Name=大海, son3=Son2 [age=10]]
Person3 [son2Name=小海, son3=Son2 [age=12]]
方法二:
显然对于多个对象的话,显然就很吃力。可以使用另一种方式,
将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。
- public class Person4 implements Serializable {
- public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException {
- Son4 son = new Son4(10);
- Person4 person1 = new Person4("大海", son);
- //通过序列化方法实现深拷贝
- ByteArrayOutputStream bos=new ByteArrayOutputStream();
- ObjectOutputStream oos=new ObjectOutputStream(bos);
- oos.writeObject(person1);
- oos.flush();
- ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
- Person4 person2=(Person4)ois.readObject();
- person1.setSon4Name("小海");
- person1.getSon4().setAge(12);
- System.out.println(person1.toString());
- System.out.println(person2.toString());
- }
- public Person4(String son4Name, Son4 son4) {
- super();
- this.son4Name = son4Name;
- this.son4 = son4;
- }
- private String son4Name;
- private Son4 son4;
- public String getSon4Name() {
- return son4Name;
- }
- public void setSon4Name(String son4Name) {
- this.son4Name = son4Name;
- }
- public Son4 getSon4() {
- return son4;
- }
- public void setSon4(Son4 son4) {
- this.son4 = son4;
- }
- @Override
- public String toString() {
- return "Person4 [son4Name=" + son4Name + ", son4=" + son4 + "]";
- }
- }
- class Son4 implements Serializable {
- private int age;
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- @Override
- public String toString() {
- return "Son2 [age=" + age + "]";
- }
- public Son4(int age) {
- super();
- this.age = age;
- }
- }
这是实现序列化接口方案,nice.
perfect!!!到位
记录下听得歌曲。
- 绝世
- (张克帆)
- 世间种种的诱惑
- 不惊不扰我清梦
- 山高路远不绝我
- 追踪你绝美的笑容
- 登高一呼时才懂
- 始终在为你心痛
- 俯首对花影摇动
- 都是东风在捉弄
- 世间种种的迷惑
- 都是因你而猜错
- 水光月光又交融
- 描述这朗朗的夜空
- 生死到头的相从
- 似狂花落叶般从容
- 当一切泯灭如梦
- 就在远山被绝世尘封
java浅拷贝和深拷贝(基础也是很重要的)的更多相关文章
- Java 浅拷贝、深拷贝,你知多少?
这是今天我们在技术群里面讨论的一个知识点,讨论的相当激烈,由于对这一块使用的比较少,所以对这一块多少有些盲区.这篇文章总结了所讨论的内容,希望这篇文章对你有所帮助. 在 Java 开发中,对象拷贝或者 ...
- Java 浅拷贝和深拷贝的理解和实现方式
Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去.举例说明:比如,对象A和对象B都属于类S,具有属性a和b.那么对对象A进行拷贝 ...
- java 浅拷贝和深拷贝 对象克隆clone
分一下几点讨论: 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 一:为什么要克隆? 大家先思考一个问题,为什么需要克隆对象?直接new一个对象不行吗? 答案是:克隆的对象可能包 ...
- 【转】Java 浅拷贝和深拷贝的理解和实现方式
Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去.举例说明:比如,对象A和对象B都属于类S,具有属性a和b.那么对对象A进行拷贝 ...
- 浅谈java浅拷贝和深拷贝
前言:深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之, 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.深拷 ...
- Java 浅拷贝和深拷贝
一看就懂的,java深拷贝浅拷贝 将一个对象的引用复制给另外一个对象,一共有三种方式.第一种方式是直接赋值,第二种方式是浅拷贝,第三种是深拷贝.所以大家知道了哈,这三种概念实际上都是为了拷贝对象啊. ...
- Java 浅拷贝,深拷贝
从Java 强引用.软引用,弱引用http://blog.csdn.net/jltxgcy/article/details/35558465一文中,我们看到把一个对象赋值给另一个对象,本质上 ...
- Java浅拷贝与深拷贝(思维导图)
图1 拷贝思维导图(点击查看图片) 1,拷贝 有两个相同属性的对象A和B,A拥有初始化值,将其值拷贝到B中,使得B拥有与A“相同”数据的属性!注意这里的相同我有加双引号! 相同可能表示这么几个意思:① ...
- java浅拷贝和深拷贝
转:http://blog.csdn.net/u014727260/article/details/55003402 实现clone的2点: 1,clone方法是Object类的一个方法,所以任何一个 ...
随机推荐
- Linux type命令的用法
一般情况下,type命令被用于判断另外一个命令是否是内置命令,但是它实际上有更多的用法. 1.判断一个名字当前是否是alias.keyword.function.builtin.file或者什么都不是 ...
- 数组C - 玛雅日历
During his last sabbatical, professor M. A. Ya made a surprising discovery about the old Maya calend ...
- 阿里云 配置FTP 无法连接问题,2017年7月后
被阿里云坑飞,2017年7月上线的安全组,我压根不知道 新服务器 配置防火墙后怎么也不起作用,也暂时关不了防火墙 iptables stop #无效 搞了半天 才知道TM 不需要在linx服务器上自 ...
- 【转】CentOS7 yum方式配置LAMP环境
采用Yum方式搭建: Apache+Mysql+PHP环境 原文地址: http://www.cnblogs.com/zutbaz/p/4420791.html 1.安装Apache yum inst ...
- NYOJ 1022 合纵连横 (并查集)
题目链接 描述 乱世天下,诸侯割据.每个诸侯王都有一片自己的领土.但是不是所有的诸侯王都是安分守己的,实力强大的诸侯国会设法吞并那些实力弱的,让自己的领土面积不断扩大.而实力弱的诸侯王为了不让自己的领 ...
- 图片轮播器——jquery插件
下载:http://files.cnblogs.com/files/wordblog/jiaoben828.rar
- app 测试基础
1. 安装和启动 (1) OTA安装测试 · app必须能够通过ota安装到测试设备上 · 如果app安装完后没有icon,那么必须能够通过其他的方法来启动这个app ...
- angular导出文件保存在本地
$scope.ev_click = function(obj){ var ev = document.createEvent("MouseEvents"); ev.initMous ...
- ASLR pe 分析
ASLR 转:http://www.cnblogs.com/dliv3/p/6411814.html 3ks @author:dlive 微软从windows vista/windows server ...
- 【swupdate文档 三】SWUpdate: 嵌入式系统的软件升级
SWUpdate: 嵌入式系统的软件升级 概述 本项目被认为有助于从存储媒体或网络更新嵌入式系统.但是,它应该主要作为一个框架来考虑,在这个框架中可以方便地向应用程序添加更多的协议或安装程序(在SWU ...