JAVA 序列化

今天锤一锤这个序列化。

序列化,名字听着牛逼,网上搜罗得知,是拿来干持久化的,啥是持久化,就是比如你一个对象创建了出来,但是虚拟机一关掉,这个对象又没了,但是我们还是想保存这个对象的属性,所以就需要将这个对象的属性保存到本地,怎么保存呢?就是序列化了。

序列化可以把对象的状态信息转为字节数组,然后再需要用到的地方又可以反序列化将其转回对象。

下面实战:

首先,一个类要想能序列化,就得先实现序列化接口,这样才能使用里面的序列化方法:

这里把User类做成可序列化的类,接着就是序列化的具体实现了

 

首先我们新建一个User对象,给他赋上属性:

接着就是通过使用 ObjectInputStream 和 ObjectOutputStream 进行对象的读写:

这里oos是将对象写入流中,再通过FileOutputStream写入文件中,最后要记得关闭流,这里虽然只关闭了ObjectOutputStream,实际上也把FileOutputStream关闭了,后者的关闭在前者的close方法中已经释放了。

 

序列化写入之后,我们将其取出:

流的转换与写入无异,在读取的时候使用的是readObject方法,赋值给对象的时候需要转换一下具体的对象类型,最后打印对象可以发现数据再次读出来了。

 

序列化是用来保存对象状态的,自然而然静态属性是不能序列化的,不信试一试:

第一句话提供了一个serialVersionUID,虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L),在 A 和 B 端都有这么一个类文件,功能代码完全一致。也都实现了 Serializable 接口,但是反序列化时总是提示不成功,原因便是这个serialVersionUID不一致。

接着便是一个静态变量,下面与上面所说的序列化对象没什么差异,在完成对象的序列化写入后,对这个静态属性进行了修改变成了10,接着再从文件中反序列化取出对象写入staticSerial,输出结果,可以看到静态属性是10。

 

再说个情况,父类的序列化:

一个已经实现序列化接口的子类,如果他的父类没有实现序列化接口,那么父类的的属性会根据他的构造方法来创建,且该构造方法必须是无参的构造方法。虽然说父类没有实现序列化接口,虚拟机是不会序列化父对象的,但是Java对象的构造是从父对象到子对象的,如果父类的无参构造方法没有对值进行修改的话,那么父类的属性都是默认的值(如int为0,string为null)。

这种情况让我们想到transient这个描述符,该描述符是将一个属性描述为不可序列化的属性,上面讲的父类如果没有实例化接口的话属性是不会序列化的,这样的话我们可以想到如果把属性提到父级当中并且不实现序列化,使得字段不被序列化。

å¾ 2. æ¡ä¾ç¨åºç±»å¾

如图所示,attr1,attr2,attr3以及attr5都不会被实例化,就算我们再有一个别的类,父类的属性始终是不会被序列化的。

 

还有一个就是可以在序列化的过程中对序列化信息加密,主要方法是在实现序列化接口的类中实现writeObject和readObject方法,因为在实现序列化的过程中,虚拟机会首先在类中尝试调用自定义实现的writeObject和readObject:

这样的话,我们就可以在自定义的方法中写入自己的加密过程:

再序列化读写过后可以发现再次读出来的对象password已经改变了。

 

序列化还有他自己独特的存储规则,下面以一个demo举例:

我们先往本地序列换写入一个对象看看文件的大小

存了个user对象,大小是106,那两个岂不是212了?再试一下:

结果第一个输出106,第二个输出111,发现只大了5,这是因为JAVA序列化机制发现写入文件的为同一个对象的时候,不会再次对对象内容存储进去,而是存储一份对象的引用,加上一些控制的信息,这些就是多出来的5了。

如果在写入第一份对象后,对对象属性进行修改,再次写入,序列化机制会认为你存储了同一个对象,所以保存的只有引用,对象的状态信息仍然是第一次写入该对象的属性:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值