使用GZIP Sterams进行序列化/反序列化是不合理的

时间:2017-02-01 17:57:04

标签: java serialization gzip throwable

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

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

第一个打印输出(false)告诉我,反序列化后得到的东西与我序列化的不同。

第二个印刷品(true)告诉对象“有点”相似。

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

为什么初始对象和序列化/反序列化的对象虽然看起来不一样但有所不同?

2 个答案:

答案 0 :(得分:1)

请查看以下对您所观察结果的解释。

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

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

  3. 您正在使用以下表达式完全相同地创建asStringtoCompare,因为这两个具有相同内容的不同字符串对象将等同,您的第3个表达式为真。 / p>

    new String(seralized.array(), Charset.forName("UTF-8"));
    
  4. 如果您需要在使用原始对象调用equals()时使反序列化对象返回true,则可以继承IllegalStateException并覆盖equals方法(此处toString情况下)。

答案 1 :(得分:1)

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

您的测试无效。