• 输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)


    对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息。 对象信息一旦写到文件上那么对象的信息就可以做到持久化了
      对象的输出流: ObjectOutputStream
      对象的输入流:  ObjectInputStream

    使用:

      对象的输出流将指定的对象写入到文件的过程,就是将对象序列化的过程,对象的输入流将指定序列化好的文件读出来的过程,就是对象反序列化的过程。既然对象的输出流将对象写入到文件中称之为对象的序列化,那么可想而知对象所对应的class必须要实现Serializable接口。(查看源码可得知:Serializable接口没有任何的方法,只是作为一个标识接口存在)。

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    public class ObjectStreamTest {
        private static final String TMP_FILE = "box.tmp";
        
        public static void main(String[] args) {
            testWrite();
            testRead();
        }
        
        private static void testWrite() {   
            try {
                ObjectOutputStream out = new ObjectOutputStream(
                        new FileOutputStream(TMP_FILE));
                out.writeBoolean(true);
                out.writeByte((byte)65);
                out.writeChar('a');
                out.writeInt(20131015);
                out.writeFloat(3.14F);
                out.writeDouble(1.414D);
                out.writeUTF("我是字符串");
                // 写入HashMap对象
                HashMap<String, String> map = new HashMap<String, String>();
                map.put("one", "red");
                map.put("two", "green");
                map.put("three", "blue");
                out.writeObject(map);
                // 写入自定义的Box对象,Box实现了Serializable接口
                Box box = new Box("desk", 80, 48);
                out.writeObject(box);
    
                out.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
     
        /**
         * ObjectInputStream 测试函数
         */
        private static void testRead() {
            try {
                ObjectInputStream in = new ObjectInputStream(
                        new FileInputStream(TMP_FILE));
                System.out.printf("boolean:%b
    " , in.readBoolean());
                System.out.printf("byte:%d
    " , (in.readByte()&0xff));
                System.out.printf("char:%c
    " , in.readChar());
                System.out.printf("int:%d
    " , in.readInt());
                System.out.printf("float:%f
    " , in.readFloat());
                System.out.printf("double:%f
    " , in.readDouble());
                System.out.printf("String:%s
    " , in.readUTF());
                // 读取HashMap对象
                HashMap map = (HashMap) in.readObject();
                Iterator<?> iter = map.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry)iter.next();
                    System.out.printf("%-6s -- %s
    " , entry.getKey(), entry.getValue());
                }
                // 读取Box对象,Box实现了Serializable接口
                Box box = (Box) in.readObject();
                System.out.println("box: " + box);
    
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    class Box implements Serializable {
    
        private static final long serialVersionUID = 1L;
        
        private int width;   
        private int height; 
        private String name;   
    
        public Box(String name, int width, int height) {
            System.out.println("Box的构造器");
            this.name = name;
            this.width = width;
            this.height = height;
        }
    
        @Override
        public String toString() {
            return "["+name+": ("+width+", "+height+") ]";
        }
    }

    console信息:

    Box的构造器
    boolean:true
    byte:65
    char:a
    int:20131015
    float:3.140000
    double:1.414000
    String:我是字符串
    three -- blue
    two -- green
    one -- red
    box: [desk: (80, 48) ]

    最后总结一下对象输入输出流使用时需要注意:

    • 1. 如果对象需要被写出到文件上,那么对象所属的类必须要实现Serializable接口。 Serializable接口没有任何的方法,是一个标识接口而已。

      2. 对象的反序列化创建对象的时候并不会调用到构造方法的,从console打印的信息可以看出。

    • 3. serialVersionUID 是用于记录class文件的版本信息的,serialVersionUID这个数字是通过一个类的类名、成员、包名、工程名算出的一个数字。
    • 4. 使用ObjectInputStream反序列化的时候,ObjeectInputStream会先读取文件中的serialVersionUID,然后与本地的class文件的serialVersionUID
    • 进行对比,如果这两个id不一致,反序列则失败。
    • 5. 如果序列化与反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个serialVersionUID,如果一类已经指定的serialVersionUID,然后在序列化与反序列化的时候,jvm都不会再自己算这个 class的serialVersionUID了。
    • 6. 如果一个对象某个数据不想被序列化到硬盘上,可以使用关键字transient修饰。
    • 7. 如果一个类维护了另外一个类的引用,则另外一个类也需要实现Serializable接口。
  • 相关阅读:
    x64 平台开发 Mapxtreme 编译错误
    hdu 4305 Lightning
    Ural 1627 Join(生成树计数)
    poj 2104 Kth Number(可持久化线段树)
    ural 1651 Shortest Subchain
    hdu 4351 Digital root
    hdu 3221 Bruteforce Algorithm
    poj 2892 Tunnel Warfare (Splay Tree instead of Segment Tree)
    hdu 4031 Attack(BIT)
    LightOJ 1277 Looking for a Subsequence
  • 原文地址:https://www.cnblogs.com/myseries/p/10757033.html
Copyright © 2020-2023  润新知