假设你有课MyClass
并且您希望确保未来的序列化兼容性,或者至少确保您不会无意中更改其序列化形式。您可以使用Verify.assertSerializedForm()
from GS Collections 测试实用程序 https://github.com/goldmansachs/gs-collections/blob/master/collections-testutils/src/main/java/com/gs/collections/impl/test/Verify.java在多数情况下。
首先编写一个测试来断言您的类具有serialVersionUID
of 0L
并且有一个空字符串的序列形式。
@Test
public void serialized_form()
{
Verify.assertSerializedForm(
0L,
"",
new MyClass());
}
运行测试。它将失败,因为字符串表示 Base64 编码并且永远不为空。
org.junit.ComparisonFailure: Serialization was broken. <Click to see difference>
当您单击查看差异时,您将看到实际的 Base64 编码。将其粘贴到空字符串内。
@Test
public void serialized_form()
{
Verify.assertSerializedForm(
0L,
"rO0ABXNyAC9jYXJhbWVsa2F0YS5zaHVrbmlfZ29lbHZhLkV4ZXJjaXNlOVRlc3QkTXlDbGFzc56U\n"
+ "hVp0q+1aAgAAeHA=",
new MyClass());
}
重新运行测试。它可能会再次失败并出现这样的错误消息。
java.lang.AssertionError: serialVersionUID's differ expected:<0> but was:<-7019839295612785318>
将新的serialVersionUID粘贴到测试中代替0L。
@Test
public void serialized_form()
{
Verify.assertSerializedForm(
-7019839295612785318L,
"rO0ABXNyAC9jYXJhbWVsa2F0YS5zaHVrbmlfZ29lbHZhLkV4ZXJjaXNlOVRlc3QkTXlDbGFzc56U\n"
+ "hVp0q+1aAgAAeHA=",
new MyClass());
}
现在测试将通过,直到您更改序列化形式。如果您意外破坏了测试(更改序列化形式),首先要做的是检查您是否已指定serialVerionUID
在可序列化类中。如果您忽略它,JVM 会为您生成它,但它非常脆弱。
public class MyClass implements Serializable
{
private static final long serialVersionUID = -7019839295612785318L;
}
如果测试仍然失败,您可以尝试通过将新字段标记为瞬态、使用 writeObject() 完全控制序列化形式等来恢复序列化形式。
如果测试仍然被破坏,您必须决定是查找并恢复破坏序列化的更改,还是将您的更改视为对序列化形式的有意更改。
当您有意更改序列化形式时,您需要更新 Base64 字符串才能通过测试。当你这样做时,它是crucial你改变serialVersionUID
同时。选择什么号码并不重要,只要它是您以前从未在课程中使用过的号码即可。约定将其更改为2L
, then 3L
等等。如果您从随机生成的serialVersionUID
(like -7019839295612785318L
在示例中),您仍然应该将数字改为2L
因为它仍然是序列化形式的第二个版本。
注:我是 GS 系列的开发人员。