• Java List 的深拷贝


    老是会遇到深拷贝与浅拷贝的问题,这里进行了一些測试。代码例如以下:

    </pre><pre name="code" class="java">/*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.*;
    
    /**
     *
     * @author User
     */
    
    class Weiz implements Serializable{//对象序列化。要实现这个接口
      private static final long serialVersionUID=123L;//序列化版本号
      double x;
      public Weiz(double a){
        x=a;
      }
    }
    
    public class test_copy {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            // TODO code application logic here
            List<Weiz> lst=new ArrayList();
            lst.add(new Weiz(1.1));
            lst.add(new Weiz(1.2));
            lst.add(new Weiz(1.3));
            System.out.println("复制前。原始lst:");
            for(int i=0;i<lst.size();++i){
              System.out.println(lst.get(i)+" "+lst.get(i).x);
            }
            //System.out.println();
            //构造函数复制                     浅拷贝
            List<Weiz> lst2=new ArrayList(lst);
            //lst2.set(1, new Weiz(2.1));
            lst2.get(0).x=2.1;
            System.out.println("构造函数复制且改动后。新的lst2:");
            for(int i=0;i<lst2.size();++i){
              System.out.println(lst2.get(i)+" "+lst2.get(i).x);
            }
            System.out.println("构造函数复制且改动后,原始lst:");
            for(int i=0;i<lst.size();++i){
              System.out.println(lst.get(i)+" "+lst.get(i).x);
            }
            
            List<Weiz> lst3=deepCopy(lst);
            lst3.get(0).x=3.1;
            System.out.println("对象序列化复制且改动后,新的lst3:");
            for(int i=0;i<lst3.size();++i){
              System.out.println(lst3.get(i)+" "+lst3.get(i).x);
            }
            System.out.println("对象序列化复制且改动后,原始lst:");
            for(int i=0;i<lst.size();++i){
              System.out.println(lst.get(i)+" "+lst.get(i).x);
            }
            
            List<Weiz> lst4=deepCopy(lst);
            lst4.get(0).x=4.1;
            System.out.println("对象序列化复制且改动后。新的lst4:");
            for(int i=0;i<lst4.size();++i){
              System.out.println(lst4.get(i)+" "+lst4.get(i).x);
            }
            System.out.println("对象序列化复制且改动后。原始lst:");
            for(int i=0;i<lst.size();++i){
              System.out.println(lst.get(i)+" "+lst.get(i).x);
            }
        }
        
        //关键代码 运行序列化和反序列化  进行深度拷贝  
        public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {  
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
            ObjectOutputStream out = new ObjectOutputStream(byteOut);  
            out.writeObject(src);  
      
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
            ObjectInputStream in = new ObjectInputStream(byteIn);  
            @SuppressWarnings("unchecked")  
            List<T> dest = (List<T>) in.readObject();  
            return dest;  
        }  
          
           //关键代码 运行序列化和反序列化  进行深度拷贝,写法不同而已,作用一样  
           //个人习惯 怎么喜欢怎么来!  
        public List deepCopy2(List src) throws IOException, ClassNotFoundException{             
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();             
            ObjectOutputStream out = new ObjectOutputStream(byteOut);             
            out.writeObject(src);                    
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());             
            ObjectInputStream in =new ObjectInputStream(byteIn);             
            List dest = (List)in.readObject();             
            return dest;         
        }   
    }
    <pre name="code" class="plain">程序结果:
    run:
    复制前:
    readdxflunwen.Weiz@c17164 1.1
    readdxflunwen.Weiz@1fb8ee3 1.2
    readdxflunwen.Weiz@61de33 1.3
    构造函数复制且改动后,新的lst2:
    readdxflunwen.Weiz@c17164 2.1
    readdxflunwen.Weiz@1fb8ee3 1.2
    readdxflunwen.Weiz@61de33 1.3
    构造函数复制且改动后,原始lst:
    readdxflunwen.Weiz@c17164 2.1
    readdxflunwen.Weiz@1fb8ee3 1.2
    readdxflunwen.Weiz@61de33 1.3
    对象序列化复制且改动后。新的lst3:
    readdxflunwen.Weiz@60aeb0 3.1
    readdxflunwen.Weiz@16caf43 1.2
    readdxflunwen.Weiz@66848c 1.3
    对象序列化复制且改动后,原始lst:
    readdxflunwen.Weiz@c17164 2.1
    readdxflunwen.Weiz@1fb8ee3 1.2
    readdxflunwen.Weiz@61de33 1.3
    对象序列化复制且改动后,新的lst4:
    readdxflunwen.Weiz@8813f2 4.1
    readdxflunwen.Weiz@1d58aae 1.2
    readdxflunwen.Weiz@83cc67 1.3
    对象序列化复制且改动后。原始lst:
    readdxflunwen.Weiz@c17164 2.1
    readdxflunwen.Weiz@1fb8ee3 1.2
    readdxflunwen.Weiz@61de33 1.3
    成功构建 (总时间: 4 秒)
    
    能够看到。用构造函数(旧List)的方法。是浅拷贝,拷贝的仅仅是List中的元素,即引用,而不是这些元素或引用指向的值。
    

    而通过对象序列化方法,则是深拷贝,是把这些引用指向的对象又一次创建了一份的。

    从打印的结果也能够看到。浅拷贝时,新list中元素的值和旧List是一样,即引用是一样的。而深拷贝时,新List中元素的值和旧List的是不一样的。即引用值是不一样的。你想一下。深拷贝是又一次创建了一份指向的对象。那么指向这个新对象的引用值当然和旧的应该是不一样的!

    对象序列化方法是參考别的文章。链接Here

    当类实现了Serializable 接口,它的对象才是可序列化的。

    实际上,Serializable 是一个空接口,它的目的仅仅是标识一个类的对象能够被序列化。

    可序列化类中的属性serialVersionUID用于标识类的序列化版本号,若不显示定义该属性,JVM会依据类的相关信息计算它的值,而类改动后的计算结果与改动前的计算结果往往不同,这样反序列化时就会因版本号不兼容而失败。

    假设一个类是可序列化的。则它的全部子类也是可序列化的。当序列化对象时,假设对象的属性又引用其它对象。则被引用的对象也必须是可序列化的。

  • 相关阅读:
    抽象类和接口
    truncate,delete和drop的区别
    PLSQL乱码问题
    Linux
    myEclipse闪退
    Java 中 Synchronized 的使用
    工厂模式
    Java中的File,IO流
    jQuery的学习
    C++中的标准模板库STL
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6932239.html
Copyright © 2020-2023  润新知