序列化在构造函数中初始化的映射

rma*_*ski 9 java serialization hashmap

我刚刚遇到了一个与Java序列化有关的有趣问题.

似乎我的地图定义如下:

Map<String, String> params = new HashMap<String, String>() {{
  put("param1", "value1");
  put("param2", "value2");
}};
Run Code Online (Sandbox Code Playgroud)

我尝试使用ObjectOutputStream将其序列化为一个文件:

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outputFile));
oos.writeObject(params);
Run Code Online (Sandbox Code Playgroud)

...我得到java.io.NotSerializableException.

但是,如果我将标准方式的值放到地图上:

Map<String, String> params = new HashMap<String, String>();
params.put("param1", "value1");
params.put("param2", "value2");
Run Code Online (Sandbox Code Playgroud)

...然后序列化工作正常.

任何人都可以告诉我它为什么会发生这些声明之间有什么区别?我认为他们应该一样,但显然我错过了一些东西.

Bri*_*new 10

第一个例子是创建一个匿名内部类.怎么样 ?

Map<String, String> params = new HashMap<String, String>() {};
Run Code Online (Sandbox Code Playgroud)

将创建一个派生自的新类HashMap(请注意以下大括号,您可以在其中放置方法,成员等)

您的地图初始化然后声明一个初始化块:

Map<String, String> params = new HashMap<String, String>() { 
                                                             { // here } 
                                                           };
Run Code Online (Sandbox Code Playgroud)

并且你称之为人口方法.

这个成语很好,但你必须要知道你正在创建一个新类,而不仅仅是一个新对象.

因为这个类是一个内部类,所以它将有一个this指向包含外部类的隐式指针.您的匿名类将是可序列化的,因为它派生自可序列化的类.但是你的外部类(由this指针引用)不是.

XStream通过反射串行化为XML的工具将发现this指针并尝试序列化周围的对象,这同样令人困惑.