20:File类与IO流-----序列化流

一:概念

在这里插入图片描述

二:ObjectOutputStream类

java.io.ObjectOutputStream类,将java对象的原始数据类型写出到文件,实现对象的持久存储。

构造方法:

public ObjectOutputStream(OutputStream out);创建一个指定OutputStream的ObjectOutputStream。

序列化操作:
1:一个对象要想序列化,必须满足两个条件:
该类必须实现java.io.Serializable接口,Seializable是一个标记接口,不实现此接口的类将不会使任何状态序列化或者反序列化,会抛出NotSerializableException.
该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用translent关键字修饰。

package Demo10;

import java.io.Serializable;

/*
  序列化和反序列化的时候,会抛出NotSerializableException 没有序列化异常。
  类通过实现java.io.Serializable接口以启用序列化功能,未有实现此接口的类将
  无法使其任何状态序列化或反序列化。
  Serializable接口也叫标记型接口。
        要进行序列化和反序列化的类必须实现Serializable接口,就会给类添加一个标记。
        当我们进行序列化和反序列化的时候,就会检测类上是否有这个标记。
            有:就可以序列化和反序列化。
            没有:就会抛出NotSerializableException异常。
*/
public class Person implements Serializable {
    private String name;
    private  int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

package Demo10;

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

/*
    java.io.ObjectOutputStream extends OutputStream
    ObjectOutputStream :对象的序列化流。
    作用:把对象以流的方式写入到文件中保存。

    构造方法:
        ObjectOutputStream(OutputStream out) 创建写入指定OutputStream的ObjectOutputStream。
        参数;
            OutputStream out:字节输出流。
    特有的成员方法:
        void writeObject(object obj) 将指定的对象写入ObjectOutputStream
    使用步骤:
        1:创建ObjectOutputStream对象,构造方法中传递字节输出流。
        2:使用ObjectOutputStream对象中方法writeObject,把对象写入到文件中。
        3:释放资源。
*/
public class Demo01ObjectOutputStream {
    public static void main(String[] args) throws IOException {
        // 1:创建ObjectOutputStream对象,构造方法中传递字节输出流。
        ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("C:\\Users\\Sky\\Desktop\\one.txt"));
        // 2:使用ObjectOutputStream对象中方法writeObject,把对象写入到文件中。
        oos.writeObject(new Person("小美女",19));
        //3:释放资源。
        oos.close();
    }
}

在这里插入图片描述

三:对象的反序列化流_ObjectInputStream

ObjectInputStream反序列流,将之前使用的ObjectOutputStream序列化的原始数据恢复对象。
构造方法:

public ObjectInputStream(InputStream in);创建一个指定InputStream的ObjectInputStream。

反序列化操作1:
如果能够找到一个对象的class文件,我们可以进行反序列化操作,调用ObjectInputStream读取对象的方法:

public final Object readObject();读取一个对象。
package Demo10;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/*
    java.io.ObjectInputStream extends InputStream
    ObjectInputStream:对象的反序列化流。
    作用:
        把文件中保存的对象,以流的方式读取出来使用。
    构造方法:
        ObjectInputStream(InputStream in)创建从指定InputStream读取的ObjectInputStream.
        参数:
                InputStream in:字节输入流。
    特有的成员方法:
        Object readObject();从ObjectInputStream读取对象。
    使用步骤:
        1:创建ObjectInputStream对象,构造方法中传递字节输入流。
        2:使用ObjectInputStream对象中的方法readObject读取保存对象的文件。
        3:释放资源,
        4:使用读取出来的对象(打印).

        readObject方法声明抛出ClassNotFoundException(class文件找不到异常)
        当不存在对象的class文件抛出此异常。
        反序列的前提:
            1:类必须实现Serializable
            2:必须存在类对应的class文件。
*/
public class Demo02ObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1:创建ObjectInputStream对象,构造方法中传递字节输入流。
        ObjectInputStream  ois =new ObjectInputStream(new FileInputStream("C:\\Users\\Sky\\Desktop\\one.txt"));
        //2:使用ObjectInputStream对象中的方法readObject读取保存对象的文件。
        Object o =ois.readObject();
        //3:释放资源,
        ois.close();
        //4:使用读取出来的对象(打印)
        System.out.println(o);
        Person p =(Person)o;
        System.out.println(p.getName()+p.getAge());
    }
}

四:transient关键字——瞬态关键字

  static关键字 :静态关键字
            静态优先非静态加载到内存中(静态优先于对象进入到内存中).static叙述的成员变量不能被序列化的,序列化的都是对象。

    transient关键字:瞬态关键字。
           被transient修饰成员变量,不能被序列化。

五:InvalidClassException异常_原理。

对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个ClassNotFoundException异常。
另外,当JVM反序列化对象时,能够找到class文件,但是class文件在序列化对象之后发生修改,那么,反序列化操作也会失败,抛出一个InvalidClassException异常。发生这个异常的原因如下:
1:该类的序列版本号与从流中读取的类描述符的版本号不匹配。
2: 该类包含未知数据类型。
3:该类没有可访问的无参数构造方法。

Serializable接口给需要序列化的类,提供了一个序列版本号。SerialVersionUID:该版本号的目的在于验证序列化的对象和对应类是否版本匹配

package Demo10;

import java.io.Serializable;

/*
  序列化和反序列化的时候,会抛出NotSerializableException 没有序列化异常。
  类通过实现java.io.Serializable接口以启用序列化功能,未有实现此接口的类将
  无法使其任何状态序列化或反序列化。
  Serializable接口也叫标记型接口。
        要进行序列化和反序列化的类必须实现Serializable接口,就会给类添加一个标记。
        当我们进行序列化和反序列化的时候,就会检测类上是否有这个标记。
            有:就可以序列化和反序列化。
            没有:就会抛出NotSerializableException异常。
   static关键字 :静态关键字
            静态优先非静态加载到内存中(静态优先于对象进入到内存中).
            被static叙述的成员变量不能被序列化的,序列化的都是对象。

    transient关键字:瞬态关键字。
           被transient修饰成员变量,不能被序列化。
*/
public class Person implements Serializable {
    private static final long serialVersionUID =1L;
    private String name;
    //private  static int age;
    private  transient int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在这里插入图片描述

六:序列化集合

1:将存有多个自定义对象的集合序列操做,保存到list.txt文件中。
2:反序列化list.txt,并遍历集合,打印对象信息。
案例分析:
1:把若干学生对象,保存到集合中。
2:把集合序列化。
3:反序列化读取时,只需要读取一次,转换为集合类型。
4:遍历集合,可以打印所有的学生信息。

package Demo10;

import java.io.*;
import java.util.ArrayList;

/*
    练习;序列化集合
        当我们想在文件中保存多个对象的时候。
        可以把多个对象存储到一个集合中,
        对集合进行序列化和反序列。
     分析:
        1:定义一个存储Person对象的ArrayList集合
        2:往ArrayList集合存储Person对象。
        3:创建一个序列化流ObjectOutputStream对象
        4:创建ObjectOutputStream对象中方法writeObject,对集合进行序列化。
        5:创建一个反序列化ObjectInputStream对象。
        6:使用ObjectInputStream对象中的方法readObject读取文件中保存的集合。
        7:把Object类型的集合转换为ArrayList类型。
        8:遍历ArrayList集合。
        9:释放资源。
*/
public class Demo03Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 1:定义一个存储Person对象的ArrayList集合
        ArrayList<Person> list =new ArrayList<>();
        // 2:往ArrayList集合存储Person对象。
        list.add(new Person("张三",21));
        list.add(new Person("李四",20));
        list.add(new Person("王五",21));
        // 3:创建一个序列化流ObjectOutputStream对象
        ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("C:\\Users\\Sky\\Desktop\\two.txt"));
        // 4:创建ObjectOutputStream对象中方法writeObject,对集合进行序列化。
        oos.writeObject(list);
        // 5:创建一个反序列化ObjectInputStream对象。
        ObjectInputStream ols =new ObjectInputStream(new FileInputStream("C:\\Users\\Sky\\Desktop\\two.txt"));
        //6:使用ObjectInputStream对象中的方法readObject读取文件中保存的集合。
        Object o=ols.readObject();
        // 7:把Object类型的集合转换为ArrayList类型。
        ArrayList<Person> list1 =(ArrayList<Person>)o;
        // 8:遍历ArrayList集合。
        for (Person p:list1){
            System.out.println(p);
        }
        //9:释放资源。
        ols.close();
        oos.close();;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值