通过 ObjectInputStream 和瞬态字段进行序列化

Mat*_*ias 2 java serialization transient objectinputstream

这个问题是关于 ObjectInputStream 以及它如何构建声明为瞬态的字段。考虑 ObjectInputStream 的一个简单用例

FileInputStream fis = new FileInputStream("t.tmp");
ObjectInputStream ois = new ObjectInputStream(fis);
SomeClass sc = (SomeClass) ois.readObject();
Run Code Online (Sandbox Code Playgroud)

SomeClass 在哪里

class SomeClass {
   int x;
   transient OtherClass y;
}

class OtherClass {
   int z;
}
Run Code Online (Sandbox Code Playgroud)

ois.readObject 之后 sc.y 的值是多少?

我要求澄清我在docs.oracle.com上读到的内容,其中指出

“反序列化过程会忽略声明为瞬态或静态的字段。对其他对象的引用会导致根据需要从流中读取这些对象。”

忽略瞬态场是什么意思?如果它们是瞬态的(即未序列化 - 我如何理解它......),如何从流中读取它们

马蒂亚斯

Gre*_*pff 5

ois.readObject 之后 sc.y 的值是多少?

Someclass.y将是“默认值”。在本例中,由于它是一个对象,因此它将是null.

忽略瞬态场是什么意思?

它们没有被序列化——它们被跳过了。来自Java 对象序列化规范

可序列化类必须执行以下操作:

  • 实现 java.io.Serialized 接口
  • 标识应该可序列化的字段(使用serialPersistentFields成员显式声明它们可序列化或使用transient关键字表示不可序列化字段。)

... 和 ...

最简单的技术是将包含敏感数据的字段标记为private transient. 瞬态字段不是持久性的,不会被任何持久性机制保存。标记该字段将防止状态出现在流中以及在反序列化期间恢复。由于(私有字段)的写入和读取不能在类外部被取代,因此类的瞬态字段是安全的。

你的下一个问题是:

如果它们是瞬态的,如何从流中读取它们

它们不在流中 - 因此,实际上,它们没有被读取。如上所述,最终作为该类型的“默认值”(null对于对象,0/false对于基元)。

“反序列化过程会忽略声明为瞬态或静态的字段。”

对于最常见的情况,它们会被序列化过程忽略 - 因此,它们不在流中,也不会被反序列化。但是,如果您在序列化对象之后更改了类,以便以前序列化的字段现在被标记为瞬态,则反序列化过程在流中找到该值时将忽略该值。