对象流

对象流

ObjectOutputStream ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。

ObjectInputStreamObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。

ObjectOutputStream / ObjectInputStream

  • 增强了缓冲区功能
  • 增强了读写8种基本数据类型和字符串的功能
  • 增强了读写对象的功能
    • readObject() 从流中读取一个对象
    • writeObject(Object obj) 向流中写入一个对象

使用流传输对象的过程称为序列化、反序列化

ObjectOutputStream 

小案例:

package com.iopractise;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 * 使用ObjectOutputStream实现对象的序列化
 */
public class Demo08 {
    public static void main(String[] args) throws IOException {
        //1.创建对象流
        FileOutputStream fos = new FileOutputStream("d:\stu.bin");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        //2.序列化(写入操作)
        Student stu1 = new Student("张三", 20);
        oos.writeObject(stu1);
        //3.关闭
        oos.close();
        System.out.println("序列化完毕");
        /**
         * 如果student类没有实现Serializable会报没有序列化异常
         * java.io.NotSerializableException
         */

    }
}

  

运行完毕之后,我们打开D盘下的stu.bin文件之后,会看到序列化之后的对象信息。(只不过是乱码的)

ͭ sr _x0016_com.iopractise.Student2"«?

 I ageL namet _x0012_Ljava/lang/String;xp   t 张三

ObjectInputStream

小案例:

package com.iopractise;

import java.io.*;

/**
 * 使用ObjectInputStream实现对象的反序列化(读取重构成对象)
 */
public class Demo09 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.创建对象流
        FileInputStream fis = new FileInputStream("d:\stu.bin");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //2.序列化(写入操作)
        Student student = (Student) ois.readObject();
        //3.关闭
        ois.close();
        System.out.println("序列化完毕");
        System.out.println(student.toString());

    }
}

  

运行结果:

序列化完毕

Student{name='张三', age=20}

 

注意:

1)如果     Student student = (Student) ois.readObject();     Student student2 = (Student) ois.readObject();连续读两次会抛出异常java.io.EOFException,表示已经读完了,就不能再读了。

2)如果实体类中又套用了其他的实体类,那么在序列化和反序列化的时候,这个套用的实体类也要实现Serializable,接口否则是会抛异常的。

3private static final long serialVersionUID = 1L;//这个值可以随便指定  这个序列化id表示的是序列化的类和反序列化的类是同一个类。这个时候,我们在执行反反序列化的类。会抛出异常:local class incompatible: stream classdesc serialVersionUID = 3603863914098147085, local class serialVersionUID = 1

解决办法也挺简单的,我们再重新执行一下序列化的类,然后再执行反序列化的类,也就是说重新序列化一次就好了。

(4)private transient int age;//如果我们对于那些不想序列化和反序列化的属性,我们可以使用transient 关键字进行修饰。transient 表示瞬时的,暂时的,如果能够序列化或者反序列化,那不就成了永久的了吗。

再次运行结果:序列化完毕

Student{name='张三', age=0};//可见age就没有被序列化。

(5)静态属性也是不能序列化或者反序列化的。比如;private static String country="中国";

(6)序列化多个对象的时候,可以借助集合来进行实现。

补充:(序列化多个对象的时候)

第一种实现方式:

//2.序列化(写入操作)
Student stu1 = new Student("张三", 20);
Student stu2 = new Student("李四", 25);
oos.writeObject(stu1);
oos.writeObject(stu2);

 

//2.序列化(写入操作)

Student student = (Student) ois.readObject();
Student studen2 = (Student) ois.readObject();
//3.关闭
ois.close();
System.out.println("序列化完毕");
System.out.println(student.toString());
System.out.println(studen2.toString());

 

第二种实现方式:通过集合的方式实现:

//2.序列化(写入操作)
Student stu1 = new Student("张三", 20);
Student stu2 = new Student("李四", 25);
ArrayList<Student> stuList = new ArrayList<Student>();
stuList.add(stu1);
stuList.add(stu2);
oos.writeObject(stuList);
//3.关闭
oos.close();
System.out.println("序列化完毕");

 

//2.序列化(写入操作)
ArrayList<Student> stuList = (ArrayList<Student>) ois.readObject();
//3.关闭
ois.close();
System.out.println("序列化完毕");
System.out.println(stuList.toString());

原文地址:https://www.cnblogs.com/dongyaotou/p/14386722.html