写在前面
上一篇文章,我们介绍了几个入门级别的序列化的问题,但是,当你了解了这些,还是会有很多新的问题在等着你,今天我们继续开始序列化和反序列化的征程。看看如下几个问题,能回答上来多少?
先看问题1.控制序列化过程时,有一个特定的子对象不愿让Java的序列化机制自动保存与恢复。比如说密码。这个时候该怎么做?
2.序列化机制保存的是什么信息,类中的方法会被保存吗?
3.声明为static和transient类型的成员数据可以被序列化吗?
4.谈谈对serialVersionUID的理解?
对特定的子对象不采取序列化先来看第一个问题:密码我们肯定不想被序列化。接着
为防止对象的敏感部分被序列化,
一个办法是将自己的类实现为Externalizable,这样一来,没有任何东西可以自动序列化,只能在 writeExternal() 明确序列化那些需要的部分。
代码为证
User.java
Test1.java
已经看不到密码了。
然而,若操作的是一个 Serializable 对象,所有序列化操作都会自动进行。为解决这个问题,可以用transient(临时)逐个字段地关闭序列化。
代码为证
User1.java
Test1.java
序列化保存的是什么信息
看看Java都对User1类序列化了哪些信息,为了便于观察使用Linux下面的strings函数
这些信息很直观的告诉我们序列化都保存了些什么内容:
1)对象的类型
2)对象属性的类型
3)对象属性的值
继续验证:在User1.java中添加2个方法:
查看序列化的信息:
没有变化。
序列化机制只保存对象的类型信息,属性的类型信息和属性值,和方法没有什么关系,无论你给这个类增加多少个方法,序列化内容也不会增加任何东西
声明为static和transient类型的成员数据可以被序列化吗?1.用transient逐个字段地关闭序列化。也就是一个类的属性被transient修饰,就不会被序列化。上面的代码已经验证。
代码验证static修饰的成员数据
User1.java
Test1.java
有人会说了,被static修饰的属性也是可以序列化。但是现实无情的欺骗了我们。
静态成员属于类级别的,所以不能序列化,序列化只是序列化了对象而已,这里“不能序列化”的意思是序列化信息中不包含这个静态成员域,下面之所以password输出还是yunxiao,是因为测试都在同一个机器(而且是同一个进程),因为这个jvm已经把password加载进来了,所以获取的是加载好的password,如果是传到另一台机器或者关掉程序重新写个程序读入object5.txt,此时因为别的机器或新的进程是重新加载password的,所以password信息就是初始时的信息,即null。所以,总结来看,静态成员是不能被序列化的,所以正确的运行结果应该是:
验证一下:序列化的代码注释。
或通过Linux中的strings查看:
静态成员是不能被序列化的,因为静态成员是随着类的加载而加载的,与类共存亡。
谈谈对serialVersionUID的理解serialVersionUID是叫做流的唯一标识符,通常也被称为序列版本UID。每个可以序列化的类都有一个唯一标识号与它相关联。
如果你没有在一个位为serialVersionUID的私有静态final的long域中显示的指定该标识号。系统就会自动地根据这个类来调用一个复杂的计算过程,从而在运行时产生该标识符。这个自动产生的值会受到类名称、它所实现的接口名称、以及所有公有的和受保护的成员的名称所影响。如果你通过任何方法改变了这些信息,比如,增加了一个不是很重要的工具方法,自动产生的序列版本UUID也会发生变化。因此,如果你没有申明一个显示的序列版本UUID,兼容性将会遭到破坏。
欢迎加入51码农网,让我们一起组队学习编程,每日打卡,一天进步一点点。www.51manong.com
关注公众号:51码农网