Java序列化

6

我在阅读《Effective Java》时遇到了一个问题,希望你能为我翻译一下。如果这个问题实在太简单和直接了当,请原谅我的无知。在第74条 - 明智地实现Serializable接口中,作者说即使你使用私有和包级私有字段对类进行了良好的信息隐藏,它仍然容易失去效力?过去我所了解的是,所有序列化只是将对象转换为字节流形式,反序列化后相同的对象会被还原回来。那么,在这个过程中,它如何失去数据隐藏呢?

3个回答

4
你可以通过序列化和反序列化来访问对象的内部状态值。
通过序列化一个对象,你可能能够读取私有字段的值,而这些字段你本来是无法访问的。相反地,如果你创建了一个精心制作的字节数组,并将其反序列化为一个实例,你可能会使它处于非法状态。

这是否意味着,每当我们序列化一个对象时,就会失去数据隐藏可能无法按照我们所期望的方式工作的保证? - t0mcat
1
在某种程度上是的,但如果您认为这可能会引起问题,您可以始终覆盖readObject()方法,自行检查状态,并在违反某些约束时抛出异常。至于访问值,在大多数实际情况下,这不是一个大问题。 - candiru

0

@candiru指出了与OOP上下文中的序列化有关的数据隐藏问题。

但是,序列化还有另一个方面。

您可以发送序列化文件通过网络,因此它可以被窥视,而应该是私有的东西很容易被侵犯。

下面是我序列化的Bean类的内容(使用默认技术)。我可以通过在文本编辑器中打开序列化文件来查看内容。

’ sr SerializationPractice1 I ageL extrat Ljava/lang/String;L nameq ~ xp
pt SidKumarq ~ x

现在,即使不知道该类的详细信息,您也可以轻松找到以下信息:

  1. 类名:SerializationPractice1
  2. 名为name的字符串属性值为SidKumar

这些事情您肯定能够注意到;其他细节并不那么清晰。以上信息是正确的。


0
我相信序列化有可能将私有数据暴露给外部世界。这就是使用Externalizable类型实例的Externalizing非常方便的地方。通过实现Externalizable接口的writeExternal(...)方法,开发人员可以完全控制序列化过程,而不是完全依赖默认的序列化运行时实现。以下是我的想法的伪代码(我会忽略实际方法签名,因为这只是一个旨在传达更广泛想法的伪代码):
    class SensitiveData implemets java.io.Externalizable{

       int sensitiveInteger;
       writeExternal (OutputData outputData){
          //encrypt sensitiveInteger here
          //serialize the sensitiveInteger which is now encrypted to any persistent store
          outputData.writeInt(sensitiveInteger);
          //do other processing
    }
 }

事实上,为什么仅仅是加密,如果我们想要在某些情况下压缩序列化到某个持久存储器的字节,那么我们可能希望这样做,尤其是当要序列化的实例很大时。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接