对象的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!!!到位
原文地址:https://www.cnblogs.com/c-h-y/p/9574586.html