为了账号安全,请及时绑定邮箱和手机立即绑定

序列化双括号初始化的 Map

序列化双括号初始化的 Map

噜噜哒 2022-07-20 20:22:28
任何人都可以在下面的示例中解释序列化问题。我有两个相同的(等于返回真)映射 - 一个以标准方式初始化,第二个用双括号初始化。第二个不能序列化(抛出 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); // trueAssert.assertTrue(m.equals(m2)); // trueAssert.assertEquals(Utils.deserialize(Utils.serialize(m2)), m2); // okAssert.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 回答

?
Cats萌萌

TA贡献1805条经验 获得超9个赞

第二个不能序列化(抛出 NotSerializableException)。


这将是因为您在非可序列化类中的非静态方法中初始化地图。


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


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


老实说,最简单的解决方案就是避免双括号初始化。它是一种过于聪明的句法软糖。


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


static Map<String, Object> doubleBrace() {

  return new HashMap<String, Object>(){

    private static final long serialVersionUID = 1L;

    {

      put("test", "String");

    }};

}

但这在某种程度上破坏了首先使用双括号初始化的简洁性。


查看完整回答
反对 回复 2022-07-20
?
慕莱坞森

TA贡献1810条经验 获得超4个赞

在这个演示中,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);

    }

}


查看完整回答
反对 回复 2022-07-20
  • 2 回答
  • 0 关注
  • 55 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信