zoukankan      html  css  js  c++  java
  • java 对象流

    对象流

    对象序列化 (Serialization)
    ObjectOutputStream  ->序列化->写对象,将对象以“二进
    制/字节”的形式写到(文件)
    ObjectInputStream  ->反序列化 ->读对象

    将 Java 对象转换成字节序列(IO 字节流)


    对象反序列化 (DeSerialization)
    从字节序列中恢复 Java 对象

    为什么序列化
    序列化以后的对象可以保存到磁盘上,也可以在网络上传输,
    使得不同的计算机可以共享对象.(序列化的字节序列是平
    台无关的

    对象序列化的条件
    只有实现了 Serializable 接口的类的对象才可以被序列化。
    Serializable 接口中没有任何的方法,实现该接口的类不需要
    实现额外的方法。
    如果对象的属性是对象,属性对应类也必须实现 Serializable
    接口

    如何实现序列化
    创建 ObjectOutputStream 对象
    调用 writeObject()输出对象

    如何实现反序列化
    创建 ObjectInputStream 对象
    调用 readObject()读取对象

    写个小例子说明一下

    因为是对象流,肯定要用到对象,先写创建个Person类,包含姓名,年龄属性,实现get() set() toString() 有参和无参构造方法,最重要的是Person类要实现Serializable接口

     1 import java.io.Serializable;
     2 
     3 public class Person implements Serializable {//具备一个能力,可序列化与反序列化的能力
     4     private String name;
     5     private int age;
     6     public Person() {
     7         super();
     8     }
     9     public Person(String name, int age) {
    10         super();
    11         this.name = name;
    12         this.age = age;
    13     }
    14     @Override
    15     public String toString() {
    16         return "Person [name=" + name + ", age=" + age + "]";
    17     }
    18     public String getName() {
    19         return name;
    20     }
    21     public void setName(String name) {
    22         this.name = name;
    23     }
    24     public int getAge() {
    25         return age;
    26     }
    27     public void setAge(int age) {
    28         this.age = age;
    29     }
    30 }
    View Code

    再写个测试类,先调用write()把对象从内存写入到磁盘,再调用read()把对象从磁盘读到内存

     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.ObjectOutput;
     7 import java.io.ObjectOutputStream;
     8 
     9 public class TestObjectOutputStream {
    10 
    11     public static void main(String[] args) {
    12         //write();
    13         read();
    14     }
    15     
    16     public static void read() {
    17         //(1)创建流对象
    18         ObjectInputStream ois = null;
    19         try {
    20             ois = new ObjectInputStream(new FileInputStream("D:\object.txt"));
    21             //(2)读对象
    22             System.out.println(ois.readInt());
    23             System.out.println(ois.readUTF());
    24             System.out.println(ois.readObject());
    25         } catch (FileNotFoundException e) {
    26             // TODO 自动生成的 catch 块
    27             e.printStackTrace();
    28         } catch (ClassNotFoundException e) {
    29             // TODO 自动生成的 catch 块
    30             e.printStackTrace();
    31         } catch (IOException e) {
    32             // TODO 自动生成的 catch 块
    33             e.printStackTrace();
    34         }finally {
    35             //(3)关闭流
    36             if(ois != null) {
    37                 try {
    38                     ois.close();
    39                 } catch (IOException e) {
    40                     // TODO 自动生成的 catch 块
    41                     e.printStackTrace();
    42                 }
    43             }
    44         }        
    45     }
    46     
    47     //写对象的方法
    48     public static void write() {
    49         //(1)创建对象流对象
    50         ObjectOutputStream oos = null;
    51         try {
    52             oos = new ObjectOutputStream(new FileOutputStream("D:\object.txt"));
    53             //(2)写对象
    54             oos.writeInt(999);
    55             oos.writeUTF("shabi");
    56             oos.writeObject(new Person("ting",20));
    57         } catch (FileNotFoundException e) {
    58             // TODO 自动生成的 catch 块
    59             e.printStackTrace();
    60         } catch (IOException e) {
    61             // TODO 自动生成的 catch 块
    62             e.printStackTrace();
    63         }finally {
    64             //(3)关闭流
    65             if(oos != null) {
    66                 try {
    67                     oos.close();
    68                 } catch (IOException e) {
    69                     // TODO 自动生成的 catch 块
    70                     e.printStackTrace();
    71                 }
    72             }
    73         }
    74     }
    75 }
    View Code

    序列化与反序列化

    序列化与反序列化
    1) 序列化能保存的元素
    a) 只能保存对象的非静态成员变量
    b) 不能保存任何成员方法和静态的成员变量(只是保存属性)
    c) 不保存 transient 成员变量
    d) 如果一个对象的成员变量是一个对象,这个对象的成 
    员变量也会保存
    e) 串行化保存的只是变量的值,对于变量的任何修饰符,
    都不能保存


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


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

    写个小例子说明一下

    先创建个Student类,实现Serializable接口,包含姓名、年龄、学校名称(static修饰)、密码(transient修饰)属性,还有get() set() toString() 有参(参数不含schoolName)和无参构造方法

     1 import java.io.Serializable;
     2 
     3 public class Student implements Serializable  {
     4     /**
     5      * 
     6      */
     7     private static final long serialVersionUID = -4502633718082654465L;
     8     private String name;
     9     private int age;
    10     public static String schoolName;//学校名称
    11     private transient String pwd; //密码 属性的值将不再被序列化
    12     public Student() {
    13         super();
    14     }
    15     public Student(String name, int age, String pwd) {
    16         super();
    17         this.name = name;
    18         this.age = age;
    19         this.pwd = pwd;
    20     }
    21     public String getPwd() {
    22         return pwd;
    23     }
    24     public void setPwd(String pwd) {
    25         this.pwd = pwd;
    26     }
    27     public String getName() {
    28         return name;
    29     }
    30     public void setName(String name) {
    31         this.name = name;
    32     }
    33     public int getAge() {
    34         return age;
    35     }
    36     public void setAge(int age) {
    37         this.age = age;
    38     }
    39     @Override
    40     public String toString() {
    41         return "Student [name=" + name + ", age=" + age + ", pwd=" + pwd + "]"+"schoolName="+schoolName;
    42     }    
    43 }
    View Code

    再写个测试类,先调用write()把对象从内存写入到磁盘,再调用read()把对象从磁盘读到内存

     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 Test {
     9     public static void main(String[] args) {
    10         //调用写对象的方法
    11         //write();
    12         //调用读对象的方法
    13         read();
    14     }
    15     public static void write(){
    16         ObjectOutputStream oos=null;
    17         try {
    18             oos=new ObjectOutputStream(new FileOutputStream("E:\student.txt"));
    19             Student stu=new Student("marry", 20, "888888");
    20             Student.schoolName="JN校区";
    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             //关闭
    30             if(oos!=null){
    31                 try {
    32                     oos.close();
    33                 } catch (IOException e) {
    34                     // TODO Auto-generated catch block
    35                     e.printStackTrace();
    36                 }
    37             }
    38         }
    39     }
    40     public static void read(){
    41         ObjectInputStream ois=null;
    42         try {
    43             ois=new ObjectInputStream(new FileInputStream("E:\student.txt"));
    44             Student stu=(Student) ois.readObject();
    45             System.out.println(stu);
    46             //结果输出:Student [name=marry, age=20, pwd=null]schoolName=null
    47             //pwd为空是因为transient修饰  schoolName为空是因为是static的
    48         } catch (FileNotFoundException e) {
    49             // TODO Auto-generated catch block
    50             e.printStackTrace();
    51         } catch (ClassNotFoundException e) {
    52             // TODO Auto-generated catch block
    53             e.printStackTrace();
    54         } catch (IOException e) {
    55             // TODO Auto-generated catch block
    56             e.printStackTrace();
    57         }finally{
    58             //关闭流
    59             if(ois!=null){
    60                 try {
    61                     ois.close();
    62                 } catch (IOException e) {
    63                     // TODO Auto-generated catch block
    64                     e.printStackTrace();
    65                 }
    66             }
    67         }
    68     }
    69 }
    View Code

    对象序列化注意事项
    1) 同一个对象多次序列化的处理
    a) 所有保存到磁盘中的对象都有一个序列化编号
    b) 序列化一个对象中,首先检查该对象是否已经序列化过

    c) 如果没有,进行序列化
    d) 如果已经序列化,将不再重新序列化,而是输出编号
    即可

    2) 如果不希望某些属性(敏感)序列化,或不希望出现递归
    序列
    a) 为属性添加 transient 关键字(完成排除在序列化之外)
    b) 自定义序列化(不仅可以决定哪些属性不参与序列化,
    还可以定义属性具体如何序列化)

    3) 序列化版本不兼容
    a) 修改了实例属性后,会影响版本号,从而导致反序列化
    不成功
    b) 解 决 方 案 : 为 Java 对 象 指 定 序 列 化 版 本 号
    serialVersionUID

  • 相关阅读:
    [LeetCode] Largest Number At Least Twice of Others 至少是其他数字两倍的最大数
    [LeetCode] Cut Off Trees for Golf Event 为高尔夫赛事砍树
    [LeetCode] Kth Smallest Number in Multiplication Table 乘法表中的第K小的数字
    [LeetCode] 746. Min Cost Climbing Stairs 爬楼梯的最小损失
    [LeetCode] Prefix and Suffix Search 前后缀搜索
    [LeetCode] Strange Printer 奇怪的打印机
    VMPlayer Ubuntu 16.04 Copy and Paste with Host 主机与宿机之间的复制粘贴
    Solve Error: "errcode": 85005, "errmsg": "appid not bind weapp hint"
    [LeetCode] Find Smallest Letter Greater Than Target 找比目标值大的最小字母
    [LeetCode] 743. Network Delay Time 网络延迟时间
  • 原文地址:https://www.cnblogs.com/bfcs/p/10422537.html
Copyright © 2011-2022 走看看