首页 > 编程语言 >Head First Java 读书笔记 14章

Head First Java 读书笔记 14章

时间:2022-11-12 23:00:33浏览次数:53  
标签:Head Java 读书笔记 对象 串流 序列化 public serialVersionUID

第14章:序列化与文件的输入输出

对象可以被序列化,也可以展开。对象有状态和行为两种属性,行为存在于类中,而状态存在于个别的对象中。本章将讨论以下两种选项:

1.如果只有自己写的Java程序会用到这些数据。用序列化(Serialization),将被序列化的对象写到文件中。然后就可以让你的程序去文件中读取序列化的对象,并把它们展开回到活生生的状态。

2.如果数据需要被其它程序引用。写一个纯文本文件,用其它程序可以解析的特殊字符写到文件中。

如何把序列化对象写入文件?

public class TestOutputStream {
public static void main(String[] args) {
try {
// 如果文件不存在,就自动创建该文件
FileOutputStream fileStream = new FileOutputStream("mygame.ser");
// 创建存取文件的 os 对象
ObjectOutputStream os = new ObjectOutputStream(fileStream);
// 把序列化对象写入文件
os.writeObject(new Dog()); // Dog必须是可序列化的类
os.writeObject(new Dog());
// 关闭所关联的输出串流
os.close();
} catch (Exception e) {
System.out.println(e);
}
}
}

什么是串流?

将串流( stream )连接起来代表来源与目的地(文件或网络端口)的连接。串流必须要连接到某处才能算是个串流。Java的输入输出API带有连接类型的串流,它代表来源与目的地之间的连接,连接串流即把串流与其它串流连接起来。

当对象被序列化时,被该对象引用的实例变量也会被序列化。且所有被引用的对象也会被序列化。最重要的是,这些操作都是自动完成的。

如果要让类能够序列化,就要实现Serializable

Serializable接口,又被称为marker或tab类的标记接口,因为此接口并没有任何方法需要被实现。它唯一的目的就是声明有实现它的类是可以被序列化的。也就是说,此类型的对象可以通过序列化的机制来存储。如果某个类是可以序列化的,则它的子类也自动地可以序列化。

// Serializable没有方法需要实现,它只是用来告诉Java虚拟机这个类可以被序列化
public class Box implements Serializable {
public Box() {}
}

注意:序列化是全有或全无的,即对象序列化时不存在“一部分序列化成功、另一部分序列化失败”的情况,如果对象有一部分序列化失败,则整个序列化过程就是失败的。只有可序列化的对象才能被写入到串流中。

那么在一个可序列化的类中,如何指定部分实例变量不执行序列化呢?

如果希望某个实例变量不能或不应该被序列化,就把它标记为 transient(瞬时)的,即可。

// Serializable没有方法需要实现,它只是用来告诉Java虚拟机这个类可以被序列化
public class Box implements Serializable {
public Box() {}

// 该id变量,就不会被序列化
transient String id;
String username;
}

如何从文件中读取序列化对象,并将其还原?

把对象恢复到存储时的状态。解序列化,可看成是序列化的反向操作。

public class TestInputStream {
public static void main(String[] args) {
try {
// 打开文件流,如果文件不存在就会报错
FileInputStream fileStream = new FileInputStream("mygame.ser");
// 创建 输入流
ObjectInputStream os = new ObjectInputStream(fileStream);
// 读取 序列化对象
Object one = os.readObject();
Object two = os.readObject();
// 类型转换,还原对象类型
Dog d1 = (Dog)one;
Dog d2 = (Dog)two;
// 关注 输入流
os.close();
} catch (Exception e) {
System.out.println(e);
}
}
}

序列化(存储)和解序列化(恢复)的过程,到底到生了什么事?

你可以通过序列化来存储对象的状态,使用ObjectOutputStream来序列化对象。Stream是连接串流或是链接用的串流,连接串流用来表示源或目的地、文件、网络套接字连接。链接用串流用来链接连接串流。使用FileOutputStream将对象序列化到文件上。静态变量不会被序列化,因为所有对象都是共享同一份静态变量值。

对象必须实现Serializable 这个接口,才能被序列化。如果父类实现了它,则子类就自动地有实现。
解序列化时,所有的类都必须能让Java虚拟机找到。读取对象的顺序必须与写入时的顺序一致。

如何把字符串写入文件文件?

try {
// FileWriter
FileWriter writer = new FileWriter("foo.txt");
writer.write("hello foo!");
writer.close();
} catch (IOException e) {
System.out.print(e);
}

什么是缓冲区?为什么使用缓冲区会提升数据读写的效率?

没有缓冲区,就好像逛超市没有推车一样,你只能一次拿一项商品去结账。缓冲区能让你暂时地摆一堆东西,直到装满为止。用了缓冲区,就可以省下好几趟的来回。

缓冲区的奥妙之处在于,使用缓冲区比没有使用缓冲区的效率更好。通过 BufferedWriter 和 FileWriter 的链接,BufferedWriter 可以暂存一堆数据,等到满的时候再实际写入磁盘,这样就可以减少对磁盘的操作次数。如果想要强制缓冲区立即写入,只要调用 writer.flush() 这个方法即可。

如何从文本文件中读取数据?

File对象表示文件,FileReader用于执行实际的数据读取,BufferedReader让读取更有效率。读取数据,使用 while 循环来逐行读取,直到 readLine() 的结果为 null 为止。这是最常见的数据读取方式(几乎所有的非序列化对象都是这样的)。

什么是 serialVersionUID?为什么要使用 serialVersionUID?

每当对象被序列化的同时,该对象(以及所有在其版图上的对象)都会被“盖”上一个类的版本识别ID,这个ID就被称为 serialVersionUID ,它是根据类的结构信息计算出来的。在对象被解序列化时,如果在对象被序列化之后类有了不同的 serialVersionUID,则解序列化会失败。虽然会失败,但你还可以有控制权。

如果你认为类有可能会深化,就把版本识别ID(serialVersionUID)放在类中。当Java尝试解序列化还原对象时,它会对比对象与Java虚拟机上的类的serialVersionUID 是否相同。如果相同,则还原成功;否则,还原将失败,Java虚拟机就会抛出异常。因此,把 serialVersionUID 放在类中,让类在演化过程中保持 serialVersionUID 不变。

public class Dog {
// 类的版本识别ID
private static final long serialVersionUID = -54662325652236L;
}

若想知道某个类的 serialVersionUID 是多少?则可以使用 Java Development Kit 里的 serialver 工具进行查询。

serialver Dog
Dog: static final long serialVersionUID = -54662325652236L;

标签:Head,Java,读书笔记,对象,串流,序列化,public,serialVersionUID
From: https://www.cnblogs.com/LvJinshuai/p/16884958.html

相关文章

  • java——继承与多态——抽象类001
    抽象的概念:          抽象方法和抽象类的格式:                抽象方法和抽象类的使用:       ......
  • 《码出高效》Chapter2面向对象-读书笔记
    《码出高效Java开发手册》第2章面向对象OOP理念抽象封装继承多态抽象是程序员的核心素质之一,体现在对业务的建模能力,以及对架构的宏观掌控力。抽象是OO思想......
  • 【《硬件架构的艺术》读书笔记】01 亚稳态的世界
    听说这本书对数字IC设计中的常见问题讲的非常清楚易懂,看了目录感觉确实都是数字设计中一些关键问题,而且一共才217页,争取这个月看完吧。书的PDF资源:链接:https://pan.baidu......
  • java注入配置文件
    `packagecom.xkcoding.properties.controller;importcn.hutool.core.lang.Dict;importcom.xkcoding.properties.property.ApplicationProperty;importcom.xkcoding.......
  • datax同步数据java简单用法
    1.到github下载源码,自己编译。同步数据支持mysql8.0,如果直接用编译好的会遇到各种问题。https://github.com/alibaba/DataX/blob/master/userGuid.mdidea导入项目,需要先......
  • 【Javaweb】做一个房产信息管理系统一
    2019级《JAVA语言程序设计》  上机考试试题                 2020.12.20  考试要求 一、本试卷为2019级《JAVA语言程......
  • 【Java】学习Java总结之JMM
    JMM介绍JMM是什么 呢?它是Java内存模型。我们都知道每个程序都有很多线程组成,既然出现线程必然会出现意想不到的问题。出现线程安全问题一般是因为主线程和工作线程数据不......
  • java——继承与多态——继承001
    继承的概述:          继承的格式:            继承中成员变量的访问特点:              ......
  • Java消费者生产者模式,并发控制。
    概论举个例子:有一个固定容量的货架,生产者放商品进来,消费者拿商品出去,为了保证正常放入和正常拿出(数据的正确性,不会出现超过容量的存放,拿到空气)。使用同步块中的wait和n......
  • JSP—El表达式,java脚本,java表达式,jstl标签库
    jsp简介JSP(全称JavaServerPages)是由SunMicrosystems公司倡导和许多公司参与共同创建的一种使软件开发者可以响应客户端请求,而动态生成HTML、XML或其他格式文档的We......