Java 之 I/O 系列 02 ——序列化(二)

Java 之 I/O 系列 目录

Java 之 I/O 系列 01 ——基础

Java 之 I/O 系列 02 ——序列化(一)

Java 之 I/O 系列 02 ——序列化(二)

继续上篇的第二个问题

如果一个类实现了Serializable接口,但是它的父类没有实现 ,这个类可不可以序列化?

Object是每个类的超类,但是它没有实现 Serializable接口,但是我们照样在序列化对象,所以说明一个类要序列化,它的父类不一定要实现Serializable接口。但是在父类中定义 的状态能被正确 的保存以及读取吗?

还是围绕上面用过的那些类来做一些修改,看下面这个例子。

Book.java这个类和上次的一样,不实现Serializable接口

 1 public class Book {
 2
 3     private int isbn;
 4     public Book(int isbn){
 5         this.isbn = isbn;
 6     }
 7     public int getIsbn() {
 8         return isbn;
 9     }
10     public void setIsbn(int isbn) {
11         this.isbn = isbn;
12     }
13
14     public String toString(){
15         return "Book [isbn = "+isbn+"]";
16     }
17
18 }

这里新定义一个类NewBook继承Book类,并且实现 Serializable接口,下面看定义

 1 ublic class NewBook extends Book implements Serializable {
 2
 3     private String author;
 4
 5     public NewBook(int isbn, String author) {
 6         super(isbn);
 7         this.author = author;
 8     }
 9
10     public String getAuthor() {
11         return author;
12     }
13
14     public void setAuthor(String author) {
15         this.author = author;
16     }
17
18     @Override
19     public String toString() {
20         return "NewBook [author=" + author + super.toString() + "]";
21     }
22 }

然后,把Student类中Book类型的实例变量修改成NewBook类型,修改后的Student类

 1 public class Student implements Serializable {
 2
 3     private NewBook book;
 4     private String name;
 5
 6     public Student(NewBook book, String name) {
 7         super();
 8         this.book = book;
 9         this.name = name;
10
11     }
12
13     public NewBook getBook() {
14         return book;
15     }
16
17
18     public void setBook(NewBook book) {
19         this.book = book;
20     }
21
22
23     public String getName() {
24         return name;
25     }
26
27
28     public void setName(String name) {
29         this.name = name;
30     }
31
32
33     public String toString() {
34         return "Student [book=" + book + ", name=" + name + "]";
35     }
36
37
38 }

Simulator类的内容不变

 1 public class Simulator {
 2     public static void main(String[] args) {
 3         new Simulator().go();
 4     }
 5
 6     private void go() {
 7         Student student = new Student(new NewBook(2014,"author11"), "xingle");
 8         try {
 9             ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test"));
10             out.writeObject(student);
11             //System.out.println(System.currentTimeMillis());
12             System.out.println("object has been written  ");
13             out.close();
14         } catch (FileNotFoundException e) {
15             e.printStackTrace();
16         } catch (IOException e) {
17             e.printStackTrace();
18         }
19
20         try {
21             ObjectInputStream in = new ObjectInputStream(new FileInputStream("test"));
22             Student stuRead = (Student) in.readObject();
23             System.out.println("object read here");
24             System.out.println(stuRead);
25         } catch (FileNotFoundException e) {
26             e.printStackTrace();
27         } catch (IOException e) {
28             e.printStackTrace();
29         } catch (ClassNotFoundException e) {
30             e.printStackTrace();
31         }
32
33     }
34
35 }

运行这个程序 ,看下输出结果:

从结果可以看出,对象写成功了,但在读取的过程中出现了问题,具体的异常原因:no validconstructor,即没有有效的构造函数,那么 到底 是哪个 类没有有效的构造函数呢,到底需要一个什么样的构造函数呢?

对于这种情况 ,即父类没有实现Serializable接口时,但其子类实现 了此接口,那么 这个子类是可以序列化的,但是在反序列化的过程 中会调用 父类 的无参构造函数,上面异常抛出的原因就是因为我们在Book类中没有一个无参的构造函数。好,那我们下面就为Book类添加一个默认的构造函数。

 1 public class Book {
 2
 3     private int isbn;
 4     //增加默认构造函数
 5     public Book(){
 6         isbn = 100;
 7         System.out.println("Book class no-arg constructor invoked..");
 8     }
 9     public Book(int isbn){
10         this.isbn = isbn;
11     }
12     public int getIsbn() {
13         return isbn;
14     }
15     public void setIsbn(int isbn) {
16         this.isbn = isbn;
17     }
18
19     public String toString(){
20         return "Book [isbn = "+isbn+"]";
21     }
22
23 }

再来执行一次程序 ,看输出结果如何:

可以看到在反序列化的过程中调用了Book类的无参构造执行一个初始化的操作。

总结一下 :如果父类没有实现Serializable接口,但其子类实现 了此接口,那么 这个子类是可以序列化的,但是在反序列化的过程 中会调用 父类 的无参构造函数,所以在其直接父类(注意是直接父类)中必须有一个无参的构造函数。

对于第2个问题的讨论就到这里,接下来我们提出第3个问题:

如果将一个对象写入某文件(比如是a),那么之后对这个对象进行一些修改,然后把修改的对象再写入文件a,那么文件a中会包含该对象的两个版本吗?

修改Simulator类如下:

Java 之 I/O 系列 02 ——序列化(二),布布扣,bubuko.com

时间: 2024-10-25 19:07:16

Java 之 I/O 系列 02 ——序列化(二)的相关文章

Java 之 I/O 系列 02 ——序列化

Java 之 I/O 系列 目录 Java 之 I/O 系列 01 ——基础 Java 之 I/O 系列 02 ——序列化 一 序列化概述 序列化,简单来讲,就是以“流”的方式来保存对象,至于保存的目标地址,可以是文件,可以是数据库,也可以是网络,即通过网络将对象从一个节点传递到另一个节点. 在Java的I/O结构中,有ObjectOutputStream和ObjectInputStream,它们可以实现将对象输出为二进制流,并从二进制流中获取对象,那为什么还需要序列化呢?这需要从Java变量的

Java 集合系列 02 Collection架构

java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 首先,我们对Collection进行说明.下面先看看Collection的一些框架类的关系图: Collection是一个接口,它主要的两个分支是:List 和 Set. List和Set都是接口,它们继承于Collection.L

小白C#窗体系列-02.二维码生成器

今天是情人节,咳,男人们带着他们的男朋友们,女人带着她们的女朋友们愉快的逛着街.逆天也就不随大众了,就继续出C#小白系列的教程了~~~ 实在没空去录教程了,就看看文档吧,大家都知道的,录教程是比较花时间的,我不想草草了事,那是对大家和我自己的不负责,视频可以以后再录,不过软件和源码以及文档得先弄好,毕竟逆天不喜欢失信与自己~~ 废话不说了,开始我们的教程吧~ 软件下载(.NET 4.0 框架)http://pan.baidu.com/s/1i3BUVNv[源码看下面] 一.设计图纸: 二.代码分

java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括InputStream)

我们以ByteArrayInputStream,拉开对字节类型的“输入流”的学习序幕.本章,我们会先对ByteArrayInputStream进行介绍,然后深入了解一下它的源码,最后通过示例来掌握它的用法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_02.html ByteArrayInputStream 介绍 ByteArrayInputStream 是字节数组输入流.它继承于InputStream.它包含一个内部缓冲区,该缓冲区包含从流

原 Java学习之Xml系列二:xml按条件查询、xml递归遍历所有元素和属性

xml中加入了几条,为了方便查询时作为示例. 话不多说见代码注释: DTD文件:SwordTypeDefinition.dtd <?xml version="1.0" encoding="UTF-8"?> <!ELEMENT SwordLibrary (Sword*)> <!ELEMENT Sword (SwordName,Price,Attack)> <!ELEMENT SwordName (#PCDATA)> &l

Java练习 SDUT-2733_小鑫の日常系列故事(二)——石头剪子布

小鑫の日常系列故事(二)--石头剪子布 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 小鑫在上幼儿园的时候,喜欢跟小伙伴健健玩石头剪子布的游戏 ,你能帮他们判断谁胜谁负么? Input 输入有两行,每一行都有可能为"Rock"(石头),"Scissors"(剪子),"Cloth"(布).第一行为小鑫的选择,第二行为健健的选择. Output 输出有一行,如果小鑫赢了

Java下用Jackson进行JSON序列化和反序列化(转)

Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行JSON和Java对象转换,下面给出一些Jackson的JSON操作方法. 一.准备工作 首先去官网下载Jackson工具包,下载地址http://wiki.fasterxml.com/JacksonDownload.Jackson有1.x系列和2.x系列,截止目前2.x系列的最新版本是2.9.0,2.x系列有3个jar包需要下载: jackson-cor

Nginx系列教程(二)| 一文带你读懂Nginx的正向与反向代理

作者:JackTian 微信公众号:杰哥的IT之旅(ID:Jake_Internet) LAMP 系列导读 01. LAMP 系列教程(一)| 详解 Linux 环境下部署 HTTPD 服务 02. LAMP 系列教程(二)| 如何在 Linux 环境下部署 AWStats 分析系统来监控 Web 站点? 03. LAMP 系列教程(三)| 一文读懂 HTTPD 服务的访问控制 04. LAMP 系列教程(四)| MySQL 数据库系统(一) 05. LAMP 系列教程(五)| MySQL 数据

Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例)

这是一个Maven提高篇的系列,包含有以下文章: Maven提高篇系列之(一)——多模块 vs 继承 Maven提高篇系列之(二)——配置Plugin到某个Phase(以Selenium集成测试为例) Maven提高篇系列之(三)——使用自己Repository(Nexus) Maven提高篇系列之(四)——使用Profile Maven提高篇系列之(五)——处理依赖冲突 Maven提高篇系列之(六)——编写自己的Plugin(本系列完) 持续交付要“自动化所有东西”,对于集成测试也是一样.集成