序列化和文件的输入输出

//序列化
FileOutputStream fileStream = new FileOutputStream("MyGame.ser");
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(characterOne);//将变量所引用的对象序列化并写入MyGame.ser这个文件,且characterOne所属的类必须继承Serializable接口(此接口没有方法需要实现,标记用接口)
os.writeObject(characterTwo);//另一个对象
os.close();


一般来说,串流要两两连接才能做出有意义的事情——其中一个表示连接,另一个则是调用方法的。为何要两个?因为连接的串流通常都是很底层的。以FileOutputStream为例,它有可以写入字节的方法。但我们通常不会直接写入字节,而是以对象层次的观点来写入,所以需要高层的连接流串。这是考虑到良好的面向对象设计,每个类只要做好一件事。这样还可以通过不同的串流组合来达到最大的适应性。

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

整个对象版图都必须正确的序列化,不然就得全部失败。比如某个对象A继承了Serializable接口,但是他有一个成员变量是其他对象B(该对象不能被序列化)的引用,那么A将不能被序列化。
如果你需要序列化程序能够跳过某个实例变量,就把它标记成transient的变量。(比如该变量必须当场创建才有意义,或者没有实现Serializable)。这个变量还是有的,只是给序列化程序的值为null。

序列化聪明得足以分辨两个对象是否相同,在此情况下只有一个对象会被存储。

//解序列化
FileInputStream fileStream = new FileInputStream("MyGame.ser");
ObjectInputStream os = new ObjectInputStream(fileStream);
Object one = os.readObject();
Object two = os.readObject();//每次调用readObject()都会从Stream中读出下一个对象,与写入顺序相同
GameCharacter elf = (GameCharacter )one;//转换对象类型
GameCharacter troll = (GameCharacter )two;
os.close();//FileInputStream会自动跟着关掉


解序列化时transient的变量是null或者是primitive主数据类型的默认值。构造函数不会执行,因为一旦执行对象的状态又变成全新的了,这不是解序列化想要的结果。
如果对象在继承树上有个不可序列化的祖先类,则该不可序列化类以及在它之上的类的构造函数(就算是可序列化也一样)就会执行。

静态变量不会被序列化,因为它不是“每个对象一个”。

对象的序列化可能会存储一些基本的类的信息(比如类名,能保证在解序列化时能找到类),其他的大部分关于类的信息都不会存储,需要时去找内存中类的定义。----自己想的

读文件的时候文件不存在不会创建,写文件时若不存在则会创建

对象被序列化的同时,该对象会被盖上一个类的版本识别ID(serialVersionUID)。如果想在类变动后还能成功还原被序列化了的对象,就要把当初的serialVersionUID放在class中,让类在演化的过程中保持相同ID。但是前提是你得要对带回旧对象的任何问题负起全责。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值