JavaSE基础九---<IO流 >print打印流,对象输入输出流,对象序列化,transient关键字

Posted 小智RE0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE基础九---<IO流 >print打印流,对象输入输出流,对象序列化,transient关键字相关的知识,希望对你有一定的参考价值。


1.print打印流


Print 打印流:只是单向地从程序中向外输出数据.
(从服务器端向客户端输出网页的打印的信息).

  • 只做输出没有输入.
  • 打印流分为字节打印流和字符打印流.

常用:
PrintWriter:字符打印流.

  • print( )方法重载了许多参数类型的方法;可以打印各种类型数据;(不是换行输出打印的)
    底层使用了write方法
  • println( )方法;换行打印输出.
  • write( )方法,封装的数据类型过少.
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class Demo01 {
    public static void main(String[] args) throws FileNotFoundException {
        //创建打印流对象.
        PrintWriter pw=new PrintWriter("F:/JAVAIO流练习使用的文件夹/打印流学习.html");

        //public void print(String s);源代码不换行输出,

        //写个四级标题;
        pw.print("<h4>从服务器响应回来的标签.</h4>");
        //五级标题;
        pw.print("<h5>从服务器响应回来的标签.</h5>");
        //百度网址的超链接;
        pw.print("<a href=\\"https://cn.bing.com\\">必应</a>");

        //public void println(String x);源代码换行输出;

        //写个四级标题;
        pw.println("<h4>从服务器响应回来的标签.</h4>");
        //五级标题;
        pw.println("<h5>从服务器响应回来的标签.</h5>");
        //百度网址的超链接;
        pw.println("<a href=\\"https://cn.bing.com\\">必应</a>");

        //write方法;
        pw.write(100);

        //关闭流
        pw.close();
    }
}

网页:

在这里插入图片描述

网页源代码:

在这里插入图片描述


2.对象输入输出流


这里所说的对象是指内存中的对象

为什么要进行对象的输出?
当内存中的数据在某些情况下(电脑关闭或者服务器终止);数据就会消失;需要将这些数据先保存下来(即对象的序列化).

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

对象的输出流:ObjectOutputStream 
对象的输入流:ObjectInputStream

具体操作:

要将序列化之后的对象保存下来,需要通过对象输出(ObjectOutputStream)将对象状态保存,再通过对象输入流(ObjectInputStream)将对象状态恢复。

  • 在ObjectInputStream 中用readObject( )方法可以直接读取一个对象.

  • ObjectOutputStream中用writeObject( )方法可以直接将对象保存到输出流中。


3.对象序列化


对象的寿命通常是随着生成该对象的程序的终止而终止。

有时需要将对象的状态保存下来,在需要的时候再将对象恢复。

对象序列化 —对象的输出流将指定的对象写入到文件的过程,就是将对象序列化的过程.

对象反序列化—对象的输入流将指定序列化好的文件读出来的过程,就是对象反序列化的过程。

对象的输出流将对象写入到文件中称之为对象的序列化,所以必须要实现Serializable接口。例如String类就实现了Serializable接口.

在这里插入图片描述


在对象序列化时,实际上是写入临时文件的:例如在api中的例子:
这里新建的FileOutputStream目标文件的后缀名为tmp.

在这里插入图片描述

注意:反序列化时的数据类型要和序列化对象时一致


序列化与反序列化过程


例如:对象序列化过程:

import java.io.*;
import java.util.Date;
public class Demo01 {
    public static void main(String[] args) throws IOException{
        //新建目标文件的对象;
        FileOutputStream fos=new FileOutputStream("F:/JAVAIO流练习使用的文件夹/序列化对象.txt");
        //创建对象输出流的对象;
        ObjectOutputStream oos=new ObjectOutputStream(fos);
        //新建字符串类对象s;
        String s="QWER";
        //新建日期对象date,
        Date date=new Date();
        //序列化对象:
        //通过writeObject方法将对象保存到输出流中;
        oos.writeObject(s);
        oos.writeObject(date);
        //关闭对象输出流;
        oos.close();  
    }
}

序列化之后,对象是以二进制形式保存了

在这里插入图片描述


反序列化:

import java.io.*;
import java.util.Date;
public class Demo01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //新建需要读取文件的对象;
        FileInputStream fis=new FileInputStream("F:/JAVAIO流练习使用的文件夹/序列化对象.txt");
        //创建对象输入流的对象;
        ObjectInputStream ois=new ObjectInputStream(fis);
        //反序列化对象:
        //通过readObject方法读取对象
        String s=(String)ois.readObject();
        Date date=(Date)ois.readObject();
        //输出到控制台;
        System.out.println(s);
        System.out.println(date);
        //关闭对象输入流
        ois.close();
    }
}

在这里插入图片描述


自定义类的,对象序列化与反序列化


Serializable接口中没有任何方法。当一个类声明实现Serializable接口后,表明该类可被序列化。
在类中可以生成一个编号private static final long serialVersionUID = -5974713180104013488L; 随机生成的且时唯一的.
serialVersionUID;用来表明实现序列化类的不同版本间的兼容性。某个类在与之对应的对象已经序列化出去后做了修改,该对象依然可以被正确反序列化.


对于需要被序列化对象的类,这个类需要去实现接口Serializable


  • 该类会默认生成一个序列化的ID(编号);在类的内容更改时,这个序列化编号也会改变;
    (即没有显式地写出编号时;当我们在第一次序列化对象之后,记性反序列化对象,此时没有问题,但是一旦更改了类的某些数据(例如,给类新增了一个新的属性,)这时默认生成的那个编号也改变了;我们是看不到那个编号的;这个情况下;再对已经序列化的对象进行反序列化;这时会出现异常.

-那么这个时候就需要显式地写出这个编号了,需要一些设置:
例如IDEA工具:点击左上角File—>选择Settings设置;—>选择Editor—>选择Inspections—>选择Java—>选择serialization issues—>选择Serializable class without ‘serialVersionUID’;然后打钩—>选择APPLY(应用)—>OK.

在这里插入图片描述


设置之后,鼠标放到类名上时,就提示去自动显示地生成编号了:

在这里插入图片描述


那么经过设置后,显式生成的编号;即使改变了类的原有内容,这个编号也不会改变,那么,反序列化时也没有异常


自定义类的序列化对象与反序列化对象:

Pet类:

import java.io.Serializable;
//注意;自定义的类需要实现接口Serializable;否则会抛异常.
public class Pet implements Serializable {
    //显式存在的编号;
    private static final long serialVersionUID = 1361506863256785916L;
    //定义属性;
    String name;
    int age;
    //构造方法.
    public Pet(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //重写toString方法.
    @Override
    public String toString() {
        return "Pet{" +
                "name='" + name + '\\'' +
                ", age=" + age +
                '}';
    }
}

序列化对象:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Demo02 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos=new FileOutputStream("F:/JAVAIO流练习使用的文件夹/自定义类的序列化.txt");
        ObjectOutputStream oos=new ObjectOutputStream(fos);
        //新建Pet类对象;
        Pet dog=new Pet("阿杰杰杰",10);
        Pet cat=new Pet("阿猫猫猫",15);
        //序列化对象;
        oos.writeObject(dog);
        oos.writeObject(cat);
        oos.close();
    }
}

在这里插入图片描述

反序列化对象:

import java.io.*;
public class Demo02 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fis=new FileInputStream("F:/JAVAIO流练习使用的文件夹/自定义类的序列化.txt");
        ObjectInputStream ois=new ObjectInputStream(fis);
        //注意,反序列化对象时的数据类型要和序列化对象数据类型一致;
        Pet dog=(Pet)ois.readObject();
        Pet cat=(Pet)ois.readObject();
        System.out.println(dog);
        System.out.println(cat);
        //关闭流;
        ois.close();
    }
}

在这里插入图片描述



4.transient关键字


transient关键字只能修饰变量,而不能修饰方法和类;
被transient修饰的属性,不会被序列化.
静态属性也不会被序列化.

例如上面的序列化对象Pet,将name用transient修饰.

在这里插入图片描述

序列化对象后;进行反序列化;
发现读取的name为null.

在这里插入图片描述


以上是关于JavaSE基础九---<IO流 >print打印流,对象输入输出流,对象序列化,transient关键字的主要内容,如果未能解决你的问题,请参考以下文章

JavaSE基础九----<IO流 >字符流,字符缓冲流

JavaSE基础九----<IO流 >流的体系和分类,字节流,字节缓冲流

JavaSE——IO流(转换流/序列化流/打印流/压缩流)&工具包Commons-io

基础IO流javaSe

javaSE (二十二)登录注册IO版本案例数据操作流内存操作流打印流标准输入输出流随机访问流合并流序列化流PropertiesNIO

JavaSE案例 04——IO流综合运用案例案例