0

我有以下代码尝试序列化/反序列化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());
}

解释代码:我正在测试我的序列化/反序列化是否兼容。

第一个打印输出(错误)告诉我反序列化后得到的任何内容都与我序列化的内容不同。

第二个打印(真)告诉对象“有点”相似。

我试图深入每个对象,看看有什么区别,所以我再次序列化它并查看字节缓冲区的内容。根据最后一次打印(真),这看起来是相同的。

为什么初始对象和经过序列化/反序列化的对象不同,虽然看起来是一样的?

4

2 回答 2

1

请为您观察到的结果找到以下解释。

  1. 调用toString一个类型的对象IllegalStateException只会返回完全限定的类名。这是来自Throwable#toString(). 因此这对于两个对象都是相同的,结果equals将是真的

    java.lang.IllegalStateException
    
  2. IllegalStateException或其父母不覆盖equals方法。因此将仅等同于它自己。由于您的反序列化将创建一个新对象,因此您的对象在引用中不相等,因此equals将返回 false (根据Object#equals)。

  3. 您使用以下表达式以完全相同的方式创建两者,而且由于这两个具有相同内容的不同字符串对象将相等,因此您的第三个表达式为真asStringtoCompare

    new String(seralized.array(), Charset.forName("UTF-8"));
    

如果您需要让反序列化的对象在调用equals()原始对象时返回 true,您可以子类化IllegalStateException并覆盖equals方法(toString在这种情况下也是如此)。

于 2017-02-01T18:19:36.260 回答
1

IllegalStateException不会覆盖Object.equals(),因此它通过==运算符使用对象标识。因此,对于不同的实例,它将始终返回 false。

您的测试无效。

于 2017-02-01T19:13:25.660 回答