猿问

序列化双括号初始化的 Map

任何人都可以在下面的示例中解释序列化问题。我有两个相同的(等于返回真)映射 - 一个以标准方式初始化,第二个用双括号初始化。第二个不能序列化(抛出 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();

    }

}


噜噜哒
浏览 56回答 2
2回答

Cats萌萌

第二个不能序列化(抛出 NotSerializableException)。这将是因为您在非可序列化类中的非静态方法中初始化地图。双括号初始化实际上只是用实例初始化器定义一个匿名类。非静态上下文中的匿名类捕获对封闭实例的引用。如果该类不可序列化,则无法序列化匿名类实例。看起来这段代码在单元测试类中;这样的类可序列化是非常不寻常的。老实说,最简单的解决方案就是避免双括号初始化。它是一种过于聪明的句法软糖。但是,如果您真的坚持使用它,您可以简单地在静态方法中进行初始化。static Map<String, Object> doubleBrace() {&nbsp; return new HashMap<String, Object>(){&nbsp; &nbsp; private static final long serialVersionUID = 1L;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; put("test", "String");&nbsp; &nbsp; }};}但这在某种程度上破坏了首先使用双括号初始化的简洁性。

慕莱坞森

在这个演示中,Map<String, Object> m = new HashMap<String, Object>(){是一个匿名的内部类,你可以System.out.println(m.getClass())用来检查m的类。public class Utilt implements Serializable {&nbsp; &nbsp; private static final long serialVersionUID = -7271914225876022793L;&nbsp; &nbsp; @Test&nbsp; &nbsp; public void UtilTest() throws IOException, ClassNotFoundException {&nbsp; &nbsp; &nbsp; &nbsp; Map<String, Object> m = new HashMap<String, Object>(){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; private static final long serialVersionUID = 1L;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put("test", "String");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }};&nbsp; &nbsp; &nbsp; &nbsp; Map<String, Object> m2 = new HashMap<String, Object>();&nbsp; &nbsp; &nbsp; &nbsp; m2.put("test", "String");&nbsp; &nbsp; &nbsp; &nbsp; Assert.assertEquals(m, m2); // true&nbsp; &nbsp; &nbsp; &nbsp; Assert.assertTrue(m.equals(m2)); // true&nbsp; &nbsp; &nbsp; &nbsp; Assert.assertEquals(Utils.deserialize(Utils.serialize(m2)), m2); // ok&nbsp; &nbsp; &nbsp; &nbsp; Assert.assertEquals(Utils.deserialize(Utils.serialize(m)), m);&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Java
我要回答