• 【Java】IO流--序列化与反序列化


    一、序列化与反序列化

    1.序列化能保存的元素 

      a) 只能保存对象的非静态成员变量(因为被static修饰的变量,即静态变量,是属于类的,不是属于对象的

      b) 不能保存任何成员方法和静态的成员变量(序列化是对属性的序列化,而不是对方法的序列化

      c) 不保存 transient 成员变量(对象中不希望被序列化的变量可以加上 transient 关键字

      d) 如果一个对象的成员变量是一个对象,这个对象的成员变量也会保存

      e) 串行化保存的只是变量的值,对于变量的任何修饰符,都不能保存

    2.使用对象流把一个对象写到文件时不仅保证该对象是序列化的,而且该对象的成员对象也必须是可序列化的

    3.如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。

    二、对象序列化注意事项

    1.同一个对象多次序列化的处理
      a) 所有保存到磁盘中的对象都有一个序列化编号
      b) 序列化一个对象中,首先检查该对象是否已经序列化
      c) 如果没有,进行序列化
      d) 如果已经序列化,将不再重新序列化,而是输出编号即可
    2. 如果不希望某些属性(敏感)序列化,或不希望出现递归序列
      a) 为属性添加 transient 关键字(完成排除在序列化之外)
      b) 自定义序列化(不仅可以决定哪些属性不参与序列化,还可以定义属性具体如何序列化)
    3. 序列化版本不兼容
      a) 修改了实例属性后,会影响版本号,从而导致反序列化不成功
      b) 解 决 方 案 : 为 Java 对 象 指 定 序 列 化 版 本 号serialVersionUID
     
    三、代码
    实验一:测试序列化能保存的元素 
    Student类
     1 import java.io.Serializable;
     2 
     3 public class Student implements Serializable{
     4     private String name;
     5     private int age;
     6     public static String schoolName;
     7     public transient String pwd;
     8     public String getName() {
     9         return name;
    10     }
    11     public void setName(String name) {
    12         this.name = name;
    13     }
    14     public int getAge() {
    15         return age;
    16     }
    17     public void setAge(int age) {
    18         this.age = age;
    19     }
    20     public String getPwd() {
    21         return pwd;
    22     }
    23     public void setPwd(String pwd) {
    24         this.pwd = pwd;
    25     }
    26     public Student(String name, int age, String pwd) {
    27         super();
    28         this.name = name;
    29         this.age = age;
    30         this.pwd = pwd;
    31     }
    32     public Student() {
    33         super();
    34     }
    35     @Override
    36     public String toString() {
    37         return "Student [name=" + name + ", age=" + age + ", pwd=" + pwd + "]" + "schoolname=" + schoolName;
    38     }
    39     
    40 }

    TestStudent类

     1 import java.io.FileInputStream;
     2 import java.io.FileNotFoundException;
     3 import java.io.FileOutputStream;
     4 import java.io.IOException;
     5 import java.io.ObjectInputStream;
     6 import java.io.ObjectOutputStream;
     7 
     8 public class TestStudent {
     9     public static void main(String[] args) {
    10 //        read();
    11         write();
    12     }
    13     
    14     public static void read() {
    15         ObjectOutputStream oos=null;
    16         try {
    17             oos = new ObjectOutputStream(new FileOutputStream("F://student.txt"));
    18             Student stu=new Student("nexfia", 20, "lvr123**");
    19             Student.schoolName="圣芙蕾雅学园";
    20             System.out.println(Student.schoolName);
    21             oos.writeObject(stu);
    22         } catch (FileNotFoundException e) {
    23             // TODO Auto-generated catch block
    24             e.printStackTrace();
    25         } catch (IOException e) {
    26             // TODO Auto-generated catch block
    27             e.printStackTrace();
    28         }finally {
    29             if(oos!=null) {
    30                 try {
    31                     oos.close();
    32                 } catch (IOException e) {
    33                     // TODO Auto-generated catch block
    34                     e.printStackTrace();
    35                 }
    36             }
    37         }
    38         
    39     } 
    40     
    41     public static void write() {
    42         ObjectInputStream ois=null;
    43         try {
    44             ois = new ObjectInputStream(new FileInputStream("F://student.txt"));
    45             Student stu=(Student) ois.readObject();
    46             System.out.println(stu);
    47         } catch (FileNotFoundException e) {
    48             // TODO Auto-generated catch block
    49             e.printStackTrace();
    50         } catch (ClassNotFoundException e) {
    51             // TODO Auto-generated catch block
    52             e.printStackTrace();
    53         } catch (IOException e) {
    54             // TODO Auto-generated catch block
    55             e.printStackTrace();
    56         }finally {
    57             if(ois!=null) {
    58                 try {
    59                     ois.close();
    60                 } catch (IOException e) {
    61                     // TODO Auto-generated catch block
    62                     e.printStackTrace();
    63                 }
    64             }
    65         }
    66         
    67     }
    68 }

     TestStudent 类 Read() 方法输出结果

     TestStudent类 Write() 方法输出结果

    实验二:测试使用对象流把一个对象写到文件时不仅保证该对象是序列化的,而且该对象的成员对象也必须是可序列化的

    Classes 类

     1 import java.io.Serializable;
     2 import java.util.ArrayList;
     3 
     4 public class Classes implements Serializable{
     5     private String classname;
     6     private ArrayList<Student> al;
     7     private String address;
     8     public String getClassname() {
     9         return classname;
    10     }
    11     public void setClassname(String classname) {
    12         this.classname = classname;
    13     }
    14     public ArrayList<Student> getAl() {
    15         return al;
    16     }
    17     public void setAl(ArrayList<Student> al) {
    18         this.al = al;
    19     }
    20     public Classes() {
    21         super();
    22     }
    23     public Classes(String classname, ArrayList<Student> al) {
    24         super();
    25         this.classname = classname;
    26         this.al = al;
    27     }
    28 }

     Student类(修改后,不再继承Serializable接口)

     1 public class Student{
     2     private String name;
     3     private int age;
     4     public static String schoolName;
     5     public transient String pwd;
     6     public String getName() {
     7         return name;
     8     }
     9     public void setName(String name) {
    10         this.name = name;
    11     }
    12     public int getAge() {
    13         return age;
    14     }
    15     public void setAge(int age) {
    16         this.age = age;
    17     }
    18     public String getPwd() {
    19         return pwd;
    20     }
    21     public void setPwd(String pwd) {
    22         this.pwd = pwd;
    23     }
    24     public Student(String name, int age, String pwd) {
    25         super();
    26         this.name = name;
    27         this.age = age;
    28         this.pwd = pwd;
    29     }
    30     public Student() {
    31         super();
    32     }
    33     @Override
    34     public String toString() {
    35         return "Student [name=" + name + ", age=" + age + ", pwd=" + pwd + "]" + "schoolname=" + schoolName;
    36     }
    37 }

     TestClasses类

     1 import java.io.FileInputStream;
     2 import java.io.FileNotFoundException;
     3 import java.io.FileOutputStream;
     4 import java.io.IOException;
     5 import java.io.ObjectInputStream;
     6 import java.io.ObjectOutputStream;
     7 import java.util.ArrayList;
     8 
     9 public class TestClasses {
    10     public static void write() {
    11         ArrayList<Student> al=new ArrayList<Student>();
    12         al.add(new Student("Lily", 21, "qaz123"));
    13         al.add(new Student("Mary", 22, "456"));
    14         al.add(new Student("Alice", 18, "222"));
    15         
    16         Classes cl=new Classes("gzcc01", al);
    17         
    18         ObjectOutputStream oos=null;
    19         try {
    20             oos = new ObjectOutputStream(new FileOutputStream("F://cl.txt"));
    21             oos.writeObject(cl);
    22         } catch (FileNotFoundException e) {
    23             // TODO Auto-generated catch block
    24             e.printStackTrace();
    25         } catch (IOException e) {
    26             // TODO Auto-generated catch block
    27             e.printStackTrace();
    28         }finally {
    29             if(oos!=null) {
    30                 try {
    31                     oos.close();
    32                 } catch (IOException e) {
    33                     // TODO Auto-generated catch block
    34                     e.printStackTrace();
    35                 }
    36             }
    37         }
    38     }
    39     
    40     public static void read() {
    41         ObjectInputStream ois=null;
    42         try {
    43             ois = new ObjectInputStream(new FileInputStream("F://cl.txt"));
    44             Classes cl=(Classes)ois.readObject();
    45             System.out.println(cl.getClassname()+"	"+cl.getAl());
    46         } catch (FileNotFoundException e) {
    47             // TODO Auto-generated catch block
    48             e.printStackTrace();
    49         } catch (ClassNotFoundException e) {
    50             // TODO Auto-generated catch block
    51             e.printStackTrace();
    52         } catch (IOException e) {
    53             // TODO Auto-generated catch block
    54             e.printStackTrace();
    55         }finally {
    56             if(ois!=null) {
    57                 try {
    58                     ois.close();
    59                 } catch (IOException e) {
    60                     // TODO Auto-generated catch block
    61                     e.printStackTrace();
    62                 }
    63             }
    64         }
    65     }
    66     
    67     public static void main(String[] args) {
    68 //        read();
    69         write();
    70     }
    71 }

     TestClassesRead()方法输出结果

    如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。

    实验三:测试序列化编号的使用

    Classes 类

    import java.io.Serializable;
    import java.util.ArrayList;
    
    public class Classes implements Serializable{
        private String classname;
        private ArrayList<Student> al;
        public String getClassname() {
            return classname;
        }
        public void setClassname(String classname) {
            this.classname = classname;
        }
        public ArrayList<Student> getAl() {
            return al;
        }
        public void setAl(ArrayList<Student> al) {
            this.al = al;
        }
        public Classes() {
            super();
        }
        public Classes(String classname, ArrayList<Student> al) {
            super();
            this.classname = classname;
            this.al = al;
        }
    }

     Student 类

    import java.io.Serializable;
    
    public class Student implements Serializable{
        private String name;
        private int age;
        public static String schoolName;
        public transient String pwd;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getPwd() {
            return pwd;
        }
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
        public Student(String name, int age, String pwd) {
            super();
            this.name = name;
            this.age = age;
            this.pwd = pwd;
        }
        public Student() {
            super();
        }
        @Override
        public String toString() {
            return "Student [name=" + name + ", age=" + age + ", pwd=" + pwd + "]" + "schoolname=" + schoolName;
        }
    }

    TestClasses 类

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.util.ArrayList;
    
    public class TestClasses {
        public static void write() {
            ArrayList<Student> al=new ArrayList<Student>();
            al.add(new Student("Lily", 21, "qaz123"));
            al.add(new Student("Mary", 22, "456"));
            al.add(new Student("Alice", 18, "222"));
            
            Classes cl=new Classes("01", al);
            
            ObjectOutputStream oos=null;
            try {
                oos = new ObjectOutputStream(new FileOutputStream("F://cl.txt"));
                oos.writeObject(cl);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(oos!=null) {
                    try {
                        oos.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
        
        public static void read() {
            ObjectInputStream ois=null;
            try {
                ois = new ObjectInputStream(new FileInputStream("F://cl.txt"));
                Classes cl=(Classes)ois.readObject();
                System.out.println(cl.getClassname()+"	"+cl.getAl());
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                if(ois!=null) {
                    try {
                        ois.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
        
        public static void main(String[] args) {
    //        read();
            write();
        }
    }

     先运行 TestClasses 类的 write() 方法将 Classes 对象 cl 写入 F:\cl.txt

    再运行 read() 方法读取

    输出结果

    01    [Student [name=Lily, age=21, pwd=null]schoolname=null, Student [name=Mary, age=22, pwd=null]schoolname=null, Student [name=Alice, age=18, pwd=null]schoolname=null]

    修改 Classes 类,增加一个 String 类型的私有属性 address

    Classes 类(修改后)

    import java.io.Serializable;
    import java.util.ArrayList;
    
    public class Classes implements Serializable{
        private String classname;
        private ArrayList<Student> al;
        private String address;
        public String getClassname() {
            return classname;
        }
        public void setClassname(String classname) {
            this.classname = classname;
        }
        public ArrayList<Student> getAl() {
            return al;
        }
        public void setAl(ArrayList<Student> al) {
            this.al = al;
        }
        public Classes() {
            super();
        }
        public Classes(String classname, ArrayList<Student> al) {
            super();
            this.classname = classname;
            this.al = al;
        }
    }

    再次运行 TestClasses 类的 read() 方法

    此时直接报错
    序列化版本不兼容问题
      a) 修改了实例属性后,会影响版本号,从而导致反序列化不成功
      b) 解 决 方 案 : 为 Java 对 象 指 定 序 列 化 版 本 号serialVersionUID
    Eclipse 中为 Classes 类和 Student 类指定 serialVersionUID
     
    删除 Classes 类的 address 属性,为 Classes 类和 Student 类指定 serialVersionUID

    运行 TestClasses 类的 write() 方法将 Classes 对象 cl 写入 F:\cl.txt 中,再运行 read() 方法读取

    修改 Classes 类,增加一个 String 类型的私有属性 address,再次运行 TestClasses 类的 read() 方法

    此次读取成功

  • 相关阅读:
    Shell中判断语句if中-z至-d的意思
    每日英语-20171129
    THINK PHP 学习笔记20171115
    每日英语-20171115
    git bash安装和基本设置
    Centos6.8搭建Git服务(git版本可选)
    一键安装lamp环境出现的问题
    用PHP实现反向代理服务器
    动词的过去式、过去分词、现在分词
    树莓派 中文
  • 原文地址:https://www.cnblogs.com/syxy/p/12318407.html
Copyright © 2020-2023  润新知