HeadFirst Java
本人有C语言基础,通过阅读Java廖雪峰网站,简单速成了java,但对其中一些入门概念有所疏漏,阅读本书以弥补。
第一章 Java入门
第二章 面向对象
第三章 变量
第四章 方法操作实例变量
第五章 程序实战
第六章 Java函数库
第七章 继承与多态
第八章 深入多态
第九章 构造器与垃圾收集器
第十章 数字与静态
第十一章 异常处理
第十二章 GUI(内部类)
第十三章 Swing
第十四章 保存对象
前言
不知不觉剩下没几章了,这一张章主要介绍对象的序列化,以及文件的输入输出(I/O)
对象有行为和状态两种属性。行为存在类中,状态则存在特定的实例中。那么想要储存对象的状态,主要有两种方式。
- 序列化——只有自己的Java程序需要这些数据
- 纯文本文件——其他程序需要数据
举个例子:
比如做一个冒险游戏,需要储存人物的状态,两种方式
将序列化对象写入文件
一般有四步,创建文件输出串流、对象输出串流、写入对象、关闭输出流
串流:stream类,本节涉及连接串流,链接用串流
连接串流:将 来源与目的地 连接起来的 串流;或 将 串流 与 其他串流/源,目的地 连接
串流两两连接:连接串流表示连接 源与目的地,链接串流衔接前者,用来调用方法
为什么不单一串流?——FileOutputStream把字节写入文件,ObjectOutputStream调用方法把对象转换成字节传给前者
每个类负责一件事,且不同串流可以多种组合,更符合面向对象需求,灵活度更高
对象序列化的过程
,1.主数据类型实例变量
2.引用变量类型的实例变量?——其遥控的对象(的状态)也被序列化!这些操作自动进行!
让某类对象能够被序列化
1.Serializable接口,继承该接口的类 即是声明它以及它的子类可以被自动序列化
java">import java.io.*;
public class Box implements Serializable {//写入对象前必须对该类声明可序列化!private int width;public setWidth(int w) {width = w;}
}
public static void main(String[] args) {Box box = new Box();try {FileOutputStream fs = new FileOutputStream("foo.ser");//创建文件输出流,创建写入字节的文件ObjectOutputStream os = new ObjectOutputStream(fs)//对象输出流,连接fs输出流os.writeObject(box);//写入对象os.close;}catch (Exception ex){}
}
2.序列化是全有或全无的
- 如果序列化某对象时,其引用其他类对象不能被序列化,则原对象序列化失败!
- 那如果某实例变量不能或者不该被序列化,咋办?——标记为transient
为什么有的变量不能被序列化?
——1.设计者忘记声明
——2.动态数据,执行期间求出,不能或不必保存。比如说网络联机,程序关闭后,联机类不再有用,应该下次执行再新建
标记transient的变量,回复时咋办?
——会以默认值返回,如引用变量返回null
两个对象的引用变量指向同一个对象?
——对象会被储存一次。其所有引用照常复原指向它
解序列化
一般五步,创建文件流、对象流、读取对象、转换对象类型,关闭流
解序列化的过程
1.对象从Stream中读取
2.JVM通过字节信息判断对象的类
3.JVM加载类(若无则抛出异常)
4.新的对象配置到堆,但构造函数不执行(否则会被初始化)!
——若有不可序列化祖先,则从其开始进行构造,其开始的所有父类状态会被初始化
为什么祖先构造?因为必须的啊,创建新的对象,其父类必然会先构造。根据前面章节的学习。
5.对象的状态被还原,标记瞬时的状态则为默认值。
>
读取对象的顺序必须与写入顺序相同
总结
思考:为什么不把类也一起序列化?
若每个序列化对象都带有类,当对象送到网络联机上时,带宽(承载数据信息量)消耗过高。
思考:静态变量?
静态变量属于类,不会被序列化。