JAVA 序列化 和 反序列化 (Externalizable Serializable) 那些事

  • Post author:
  • Post category:java


序列化控制

  • 当我们对序列化进行控制时,可能某个特定子对象不想让Java序列化机制自动保存与恢复。如果子对象表示的是我们不希望将其序列化的敏感信息(如密码),通常会面临这种情况。即使对象中的这些信息是private属性,一经序列化处理,人们就可以通过读取文件或者拦截网络传输的方式来访问到它。有两种办法可以防止对象的敏感部分被序列化:

    • 实现

      Externalizable

      代替实现

      Serializable

      接口来对序列化过程进行控制,

      Externalizable

      继承了

      Serializable

      接口,同时增添了两个方法:

      writeExternal()



      readExternal()


    两者在反序列化时的区别





    – 对Serializable对象反序列化时,


    由于Serializable对象完全以它存储的二进制位为基础来构造,因此并不会调用任何构造函数,


    因此Serializable类无需默认构造函数,但是当Serializable类的父类没有实现Serializable接口时,反序列化过程会调用父类的默认构造函数,因此该父类必需有默认构造函数,否则会抛异常。




    – 对Externalizable对象反序列化时,



    会先调用类的不带参数的构造方法

    ,这是有别于默认反序列方式的


    。如果把类的不带参数的构造方法删除,或者把该构造方法的访问权限设置为private、默认或protected级别,会抛出


    java.io.InvalidException: no valid constructor


    异常,因此


    Externalizable对象必须有默认构造函数,而且必需是public的。





    Externalizable

    的替代方法:如果不是特别坚持实现Externalizable接口,那么还有另一种方法。我们可以实现

    Serializable

    接口,并添加

    writeObject()



    readObject()

    的方法。一旦对象被序列化或者重新装配,就会分别调用那两个方法。也就是说,

    只要提供了这两个方法,就会优先使用它们,而不考虑默认的序列化机制。

    这些方法必须含有下列准确的签名:

    private void writeObject(ObjectOutputStream stream) 
            throws IOException;
    private void readObject(ObjectInputStream stream)
            throws IOException, ClassNotFoundException
    



    – 可以用

    transient

    关键字逐个字段地关闭序列化,它的意思是“

    不用麻烦你保存或恢复数据—我自己会处理的

    ”。由于Externalizable对象在默认情况下不保存它们的任何字段,所以

    transient关键字只能和Serializable对象一起使用。



版权声明:本文为bigtree_3721原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。