标签:资料 style ret str art one 代码 图片 第四章
先放一段代码
Point.java
1 public class Point { 2 private int i; 3 4 public Point(int i) { 5 this.i = i; 6 } 7 8 public int getI() { 9 return i; 10 } 11 12 public void setI(int i) { 13 this.i = i; 14 } 15 }
PointTest.java
1 public class PointTest { 2 public static void main(String[] args) { 3 //创建一个Point对象,使用pa这个引用变量来指向它 4 Point pa = new Point(5); 5 //创建一个pb引用变量,将pa的值赋值给pb 6 Point pb = pa; 7 //改变pa中的属性的值 8 pa.setI(3); 9 //显示pb中的值 10 System.out.println(pb.getI()); 11 } 12 }
输出的值为:3
因为pa和pb指向的是同一个对象(地址),改变其中任何一个都会改变该对象的内容。
那么如何做到分开呢?就是改变pa的时候不让pb发生改变(一般用于设置中间变量),这里就涉及到对象的复制。
将Point类修改为Point2类:
1 public class Point2 implements Cloneable { 2 private int i; 3 4 public Point2(int i) { 5 this.i = i; 6 } 7 8 public int getI() { 9 return i; 10 } 11 12 public void setI(int i) { 13 this.i = i; 14 } 15 16 @Override 17 public Object clone() throws CloneNotSupportedException { 18 return super.clone(); 19 } 20 }
Point2Test.java
public class Point2Test { public static void main(String[] args) throws CloneNotSupportedException { //创建一个Point2对象,使用p2a这个引用变量来指向它 Point2 p2a = new Point2(5); //创建一个新对象,它是p2a的克隆,然后将这个新对象的引用赋值个p2b Point2 p2b = (Point2)p2a.clone(); //改变p2a中的属性的值 p2a.setI(3); //显示p2b中的值 System.out.println(p2b.getI()); } }
输出的值为:5
p2a和p2b是内容相容的不同对象。
Object类中的clone方法将原始对象的每个数据域复制给目标对象:
1.如果一个数据域是基本类型,复制的就是它的值;
2.如果一个数据域是对象,那么复制的就是它的引用。注意这里是它的引用。
如果Point2类中有一个数据域Address类,那么虽然p2a==p2b为假,但是p2a.address==p2b.address为真。
所以这称之为浅拷贝。
Address类
1 public class Address implements Cloneable { 2 private String addressName; 3 4 public String getAddressName() { 5 return addressName; 6 } 7 8 public void setAddressName(String addressName) { 9 this.addressName = addressName; 10 } 11 12 @Override 13 public Object clone() throws CloneNotSupportedException { 14 return super.clone(); 15 } 16 }
Point3类
1 public class Point3 implements Cloneable { 2 private int i; 3 private Address address; 4 5 public Point3(int i) { 6 this.i = i; 7 } 8 9 public int getI() { 10 return i; 11 } 12 13 public void setI(int i) { 14 this.i = i; 15 } 16 17 public Address getAddress() { 18 return address; 19 } 20 21 public void setAddress(Address address) { 22 this.address = address; 23 } 24 25 @Override 26 public Object clone() throws CloneNotSupportedException { 27 Point3 p3 = null; 28 p3 = (Point3) super.clone(); 29 p3.address = (Address) address.clone(); 30 31 return p3; 32 } 33 }
Point3Test.java
1 public class Point3Test { 2 public static void main(String[] args) throws CloneNotSupportedException { 3 //初始化对象p3a 4 Point3 p3a = new Point3(5); 5 Address address = new Address(); 6 address.setAddressName("位置1"); 7 p3a.setAddress(address); 8 9 //复制对象 10 Point3 p3b = (Point3) p3a.clone(); 11 12 //改变p3a的address 13 address.setAddressName("位置2"); 14 15 //输出结果比较 16 System.out.println("p3a的i: " + p3a.getI() + " p3a的address: " + 17 p3a.getAddress().getAddressName()); 18 System.out.println("p3b的i: " + p3b.getI() + " p3b的address: " + 19 p3b.getAddress().getAddressName()); 20 } 21 }
结果如图:
结论:如果在拷贝一个对象时,要想让这个拷贝的对象和源对象完全彼此独立,那么在引用链上的每一级对象都要被显式的拷贝。所以创建彻底的深拷贝是非常麻烦的,尤其是在引用关系非常复杂的情况下。
所以有了如下一点,阿里巴巴Java开发手册第四章第19条:
【推荐】慎用 Object 的 clone 方法来拷贝对象。
说明: 对象的 clone 方法默认是浅拷贝,若想实现深拷贝需要重写 clone 方法实现属性对象的拷贝。
参考资料:
https://www.cnblogs.com/dolphin0520/p/3700693.html
https://blog.csdn.net/u014727260/article/details/55003402
本文系原创,转载请注明出处,谢谢。
标签:资料 style ret str art one 代码 图片 第四章
原文地址:https://www.cnblogs.com/liufuyi/p/9319087.html