zoukankan      html  css  js  c++  java
  • 对象的复制

    问题

    先放一段代码

    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

    本文系原创,转载请注明出处,谢谢。

  • 相关阅读:
    数据结构之队列java版
    SPSS-相关性和回归分析(一元线性方程)案例解析(转)
    SPSS-非参数检验—两独立样本检验 案例解析(转)
    spss-非参数检验-K多个独立样本检验( Kruskal-Wallis检验)案例解析(转)
    SPSS-Friedman 秩和检验-非参数检验-K个相关样本检验 案例解析(转)
    SPSS-多重响应-频率和交叉表案例分析(问卷调查分析)(转)
    SPSS—回归—多元线性回归(转)
    SPSS—回归—曲线估计方程案例解析(转)
    SPSS—非线性回归(模型表达式)案例解析(转)
    SPSS—二元Logistic回归(转)
  • 原文地址:https://www.cnblogs.com/qintang/p/9319087.html
Copyright © 2011-2022 走看看