打字猴:1.700439126e+09
1700439126
1700439127 }
1700439128
1700439129 此时虽然生产者和消费者对应的类版本不同,但是显式声明的serialVersionUID相同,反序列化也是可以运行的,所带来的业务问题就是消费端不能读取到新增的业务属性(age属性)而已。
1700439130
1700439131 通过此例,我们的反序列化实现了版本向上兼容的功能,使用V1.0版本的应用访问了一个V2.0版本的对象,这无疑提高了代码的健壮性。我们在编写序列化类代码时,随手加上serialVersionUID字段,也不会给我们带来太多的工作量,但它却可以在关键时候发挥异乎寻常的作用。
1700439132
1700439133 注意 显式声明serialVersionUID可以避免对象不一致,但尽量不要以这种方式向JVM“撒谎”。
1700439134
1700439135
1700439136
1700439137
1700439138 编写高质量代码:改善Java程序的151个建议 [:1700438079]
1700439139 编写高质量代码:改善Java程序的151个建议 建议12:避免用序列化类在构造函数中为不变量赋值
1700439140
1700439141 我们知道带有final标识的属性是不变量,也就是说只能赋值一次,不能重复赋值,但是在序列化类中就有点复杂了,比如有这样一个类:
1700439142
1700439143 public class Person implements Serializable{
1700439144
1700439145 private static final long serialVersionUID=71282334L;
1700439146
1700439147 //不变量
1700439148
1700439149 public fnal String name=“混世魔王”;
1700439150
1700439151 }
1700439152
1700439153 这个Person类(此时V1.0版本)被序列化,然后存储在磁盘上,在反序列化时name属性会重新计算其值(这与static变量不同,static变量压根就没有保存到数据流中),比如name属性修改成了“德天使”(版本升级为V2.0),那么反序列化对象的name值就是“德天使”。保持新旧对象的final变量相同,有利于代码业务逻辑统一,这是序列化的基本规则之一,也就是说,如果final属性是一个直接量,在反序列化时就会重新计算。对这基本规则不多说,我们要说的是final变量另外一种赋值方式:通过构造函数赋值。代码如下:
1700439154
1700439155 public class Person implements Serializable{
1700439156
1700439157 private static final long serialVersionUID=91282334L;
1700439158
1700439159 //不变量初始不赋值
1700439160
1700439161 public final String name;
1700439162
1700439163 //构造函数为不变量赋值
1700439164
1700439165 public Person(){
1700439166
1700439167 name=“混世魔王”;
1700439168
1700439169 }
1700439170
1700439171 }
1700439172
1700439173 这也是我们常用的一种赋值方式,可以把这个Person类定义为版本V1.0,然后进行序列化,看看有什么问题没有,序列化的代码如下所示:
1700439174
1700439175 public class Serialize{
[ 上一页 ]  [ :1.700439126e+09 ]  [ 下一页 ]