课程咨询 :186 8716 1620      qq:2066486918

昆明Java培训 > 达内新闻 > 避免用序列化类在构造函数中为不变量赋值
  • 避免用序列化类在构造函数中为不变量赋值

    发布:昆明Java培训      来源:达内新闻      时间:2016-09-30

  • 昆明Java培训机构的老师知道带有final标识的属性是不变量,也就是只能赋值一次,不能重复赋值,但是在序列化类中就有点复杂了,比如这个类:

    1 public class Person implements Serializable {

    2    private static final long serialVersionUID = 1867341609628930239L;

    3    public final String perName="程咬金";

    4}

    这个Peson类(此时V1.0版本)被序列化,然后存储在磁盘上,在反序列化时perName属性会重新计算其值(这与static变量不同,static变量压根就没有保存到数据流中)比如perName属性修改成了"秦叔宝"(版本升级为V2.0),那么反序列化的perName值就是"秦叔宝"。保持新旧对象的final变量相同,有利于代码业务逻辑统一,这是序列化的基本原则之一,也就是说,如果final属性是一个直接量,在反序列化时就会重新计算。对于基本原则不多说,现在说一下final变量的另一种赋值方式:通过构造函数赋值。代码如下:

    public class Person implements Serializable {

    private static final long serialVersionUID = 1867341609628930239L;

    public final String perName;

    public Person() {

    perName = "程咬金";

    }

    }

    这也是我们常用的一种赋值方式,可以把Person类定义为版本V1.0,然后进行序列化,看看序列化后有什么问题,序列化代码如下:

    public class Serialize {

    public static void main(String[] args) {

    //序列化以持久保持

    SerializationUtils.writeObject(new Person());

    }

    }

    Person的实习对象保存到了磁盘上,它时一个贫血对象(承载业务属性定义,但不包含其行为定义),我们做一个简单的模拟,修改一下PerName值代表变更,要注意的是serialVersionUID不变,修改后的代码如下:

    public class Person implements Serializable {

    private static final long serialVersionUID = 1867341609628930239L;

    public final String perName;

    public Person() {

    perName = "秦叔宝";

    }

    }

    此时Person类的版本时V2.0但serialVersionUID没有改变,仍然可以反序列化,代码如下:

    public class Deserialize {

    public static void main(String[] args) {

    Person p = (Person) SerializationUtils.readObject();

    System.out.println(p.perName);

    }

    }

    现在问题出来了,打印出来的结果是"程咬金"还是"秦叔宝"?答案是:"程咬金"。final类型的变量不是会重新计算嘛,打印出来的应该是秦叔宝才对呀。为什么会是程咬金?这是因为这里触及到了反序列化的两一个原则:反序列化时构造函数不会执行.

    反序列化的执行过程是这样的:JVM从数据流中获取一个Object对象,然后根据数据流中的类文件描述信息(在序列化时,保存到磁盘的对象文件中包含了类描述信息,注意是描述信息,不是类)查看,发现是final变量,需要重新计算,于是引用Person类中的perName值,而此时JVM又发现perName竟没有赋值,不能引用,于是它很聪明的不再初始化,保持原值状态,所以结果就是"程咬金"了。

    注意:在序列化类中不使用构造函数为final变量赋值.

    了解详情请登陆昆明达内Java培训官网(km.Java.tedu.cn)!

    推荐文章

上一篇:java培训:显示声明UID

下一篇:避免为final变量复杂赋值

最新开班日期  |  更多

Java--零基础全日制班

Java--零基础全日制班

开班日期:12/29

Java--零基础业余班

Java--零基础业余班

开班日期:12/29

Java--周末提升班

Java--周末提升班

开班日期:12/29

Java--零基础周末班

Java--零基础周末班

开班日期:12/29

  • 网址:http://km .java.tedu.cn      地址:昆明市官渡区春城路62号证券大厦附楼6楼
  • 课程培训电话:186 8716 1620      qq:2066486918    全国服务监督电话:400-827-0010
  • 服务邮箱 ts@tedu.cn
  • 2001-2016 达内国际公司(TARENA INTERNATIONAL,INC.) 版权所有 京ICP证08000853号-56