序列化双括号初始化Map

时间:2019-03-06 07:05:03

标签: java

任何人都可以在下面的示例中解释序列化问题。我有两个相同的地图(等于返回true)-一个以标准方式初始化,另一个以双花括号初始化。第二个不能序列化(引发NotSerializableException)。

Map<String, Object> m = new HashMap<String, Object>(){
    private static final long serialVersionUID = 1L;
{
    put("test", "String");
}};
Map<String, Object> m2 = new HashMap<String, Object>();
m2.put("test", "String");       

Assert.assertEquals(m, m2); // true
Assert.assertTrue(m.equals(m2)); // true
Assert.assertEquals(Utils.deserialize(Utils.serialize(m2)), m2); // ok
Assert.assertEquals(Utils.deserialize(Utils.serialize(m)), m); // java.io.NotSerializableException on serialize()

实用程序类:

public class Utils {
    static public Object deserialize(byte[] b) throws IOException, ClassNotFoundException {
        ObjectInputStream ins = null;
        try {
            ByteArrayInputStream bais = new ByteArrayInputStream(b);
            ins = new ObjectInputStream(bais);
            return ins.readObject();
        } finally {
            if(ins != null) {
                ins.close();
            }
        }
    }

    static public byte[] serialize(Object o) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(o);
        oos.flush();
        oos.close();
        bos.close();
        return bos.toByteArray();
    }
}

2 个答案:

答案 0 :(得分:1)

  

第二个不能序列化(引发NotSerializableException)。

这是因为您正在以不可序列化的类内的非静态方法初始化地图。

双括号初始化实际上只是使用实例初始化程序定义一个匿名类。非静态上下文中的匿名类捕获对封闭实例的引用。

如果该类不可序列化,则无法序列化您的匿名类实例。看起来这段代码在单元测试类中;这样的类可序列化是非常不寻常的。

老实说,最简单的解决方案是避免双括号初始化。这是一种语法错误,太聪明了。

但是,如果您真的坚持使用它,则可以简单地以静态方法进行初始化。

static Map<String, Object> doubleBrace() {
  return new HashMap<String, Object>(){
    private static final long serialVersionUID = 1L;
    {
      put("test", "String");
    }};
}

但这在某种程度上不利于首先使用双括号初始化的简洁性。

答案 1 :(得分:0)

在此演示中,Map<String, Object> m = new HashMap<String, Object>(){是匿名内部类,您可以使用System.out.println(m.getClass())来检查 m 的类。

public class Utilt implements Serializable {
    private static final long serialVersionUID = -7271914225876022793L;

    @Test
    public void UtilTest() throws IOException, ClassNotFoundException {
        Map<String, Object> m = new HashMap<String, Object>(){
            private static final long serialVersionUID = 1L;
            {
                put("test", "String");
            }};
        Map<String, Object> m2 = new HashMap<String, Object>();
        m2.put("test", "String");

        Assert.assertEquals(m, m2); // true
        Assert.assertTrue(m.equals(m2)); // true
        Assert.assertEquals(Utils.deserialize(Utils.serialize(m2)), m2); // ok
        Assert.assertEquals(Utils.deserialize(Utils.serialize(m)), m);
    }
}