You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Map反序列化异常:单级Map反序列化为多级Map为何无即时报错?

Java序列化反序列化中的泛型类型擦除问题

问题现象

将一个Map<String, Object>对象序列化后,反序列化时强制转换为Map<String, Map<String, Object>>类型未抛出预期异常,调用restoredDoubleMap.get("KEY").keySet()时却触发ClassCastException。测试代码如下:

@Test
public void test() throws IOException, ClassNotFoundException {
    // Map of objects
    Map<String, Object> singleMap = Map.of("KEY", "VALUE");
    byte[] serializedMap;
    try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos)) {
      oos.writeObject(singleMap);
      serializedMap = bos.toByteArray();
    }

    // Map of maps of objects
    Map<String, Map<String, Object>> restoredDoubleMap;
    try (ByteArrayInputStream bis = new ByteArrayInputStream(serializedMap);
        ObjectInputStream ois = new ObjectInputStream(bis)) {
      // 预期会抛出异常但实际没有
      restoredDoubleMap = (Map<String, Map<String, Object>>) ois.readObject();
    }

    // 这行判断为true
    assertTrue(restoredDoubleMap instanceof Map<String, Map<String, Object>>);
    
    // 两个Map的equals判断通过
    assertEquals(singleMap, restoredDoubleMap);

    System.out.println(singleMap); // 输出: {KEY=VALUE}
    System.out.println(restoredDoubleMap); // 输出: {KEY=VALUE} ???

    // 这里触发ClassCastException
    System.out.println(restoredDoubleMap.get("KEY").keySet());
}

原因解析

  • 泛型类型擦除导致运行时无泛型校验:Java泛型是编译期特性,运行时所有泛型参数都会被擦除,序列化过程中只会保存对象的原始类型(这里就是Map),不会记录泛型的具体参数。因此反序列化时,JVM无法校验你强制转换的泛型类型是否匹配,所以(Map<String, Map<String, Object>>) ois.readObject()不会抛出异常。

  • instanceof的泛型检查无效:assertTrue(restoredDoubleMap instanceof Map<String, Map<String, Object>>);这行代码在编译后,泛型信息会被擦除,实际执行的是restoredDoubleMap instanceof Map,而反序列化得到的确实是Map对象,所以判断必然为true,它并没有验证泛型参数的正确性。

  • 类型错误延迟到实际使用时暴露:当调用restoredDoubleMap.get("KEY").keySet()时,get("KEY")返回的实际是String类型的"VALUE",但代码中期望它是Map<String, Object>。只有当尝试调用Map的keySet()方法时,JVM才会进行实际的类型检查,发现String无法转换为Map,从而抛出ClassCastException。

  • equals方法不关心泛型类型:assertEquals(singleMap, restoredDoubleMap)能通过,是因为Map的equals方法只比较键值对的内容是否一致,和泛型参数无关。两个Map的键都是"KEY",值都是"VALUE",所以equals返回true。

内容的提问来源于stack exchange,提问作者sdorof

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:03:37