我有以下代码尝试序列化/反序列化 Throwable
public void test() throws IOException, ClassNotFoundException {
IllegalStateException exception = new IllegalStateException("Oooops!");
ByteBuffer seralized = serialize(exception);
String asString = new String(seralized.array(), Charset.forName("UTF-8"));
Throwable deserialized = deserialize(seralized);
// false
System.out.println(exception.equals(deserialized));
// true
System.out.println(exception.toString().equals(deserialized.toString()));
seralized = serialize(deserialized);
String toCompare = new String(seralized.array(), Charset.forName("UTF-8"));
// true
System.out.println(asString.equals(toCompare));
}
private Throwable deserialize(ByteBuffer seralized) throws IOException, ClassNotFoundException {
return (Throwable) new ObjectInputStream(new GZIPInputStream(
new ByteArrayInputStream(seralized.array()))).readObject();
}
private ByteBuffer serialize(Throwable exception) throws IOException {
ByteArrayOutputStream causeBytesOut = new ByteArrayOutputStream();
ObjectOutputStream causeOut = new ObjectOutputStream(
new GZIPOutputStream(causeBytesOut));
causeOut.writeObject(exception);
causeOut.close();
return ByteBuffer.wrap(causeBytesOut.toByteArray());
}
解释代码:我正在测试我的序列化/反序列化是否兼容。
第一个打印输出(错误)告诉我,反序列化后得到的内容与序列化后得到的内容不同。
第二个打印(true)表明这些对象“有些”相似。
我试图深入研究每个对象,看看有什么区别,所以我再次序列化它并查看字节缓冲区的内容。根据最后一次打印,这看起来是相同的(正确)。
为什么初始对象和经过序列化/反序列化的对象虽然看起来相同,但不同?
最佳答案
请对您观察到的结果进行以下解释。
调用
toString
在IllegalStateException
类型的对象上将简单地返回完全限定的类名。这是来自Throwable#toString()
。因此这对于两个对象来说是相同的,equals
的结果将会是真的java.lang.IllegalStateException
IllegalStateException
或者它的 parent 不会覆盖equals
方法。因此将仅等于其自身。由于您的反序列化将创建一个新对象,因此您的对象在引用中不相等,因此equals
将返回 false(根据Object#equals
)。您正在创建
asString
和toCompare
完全相同的方式,使用下面的表达式,也因为这两个具有相同内容的不同字符串对象将相等,所以你的第三个表达式是正确的。new String(seralized.array(), Charset.forName("UTF-8"));
如果您需要让反序列化对象在调用 equals()
时返回 true使用原始对象,您可以子类 IllegalStateException
并覆盖equals
方法(在本例中也是 toString
。)。
关于java - GZIP Streams 的序列化/反序列化不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41986506/