序列化在构造函数中初始化的映射
我刚刚遇到一个与Java序列化相关的有趣问题。序列化在构造函数中初始化的映射
看来,如果我的地图定义是这样的:
Map<String, String> params = new HashMap<String, String>() {{
put("param1", "value1");
put("param2", "value2");
}};
我尝试将其序列与ObjectOutputStream的文件:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outputFile));
oos.writeObject(params);
...我得到java.io. NotSerializableException。
但是,如果不是我把值到地图的标准方式:
Map<String, String> params = new HashMap<String, String>();
params.put("param1", "value1");
params.put("param2", "value2");
...然后系列化做工精细。
有人可以告诉我为什么会发生,这些陈述之间有什么区别?我认为他们应该同样工作,但显然我错过了一些东西。
第一个例子是创建一个匿名内部类。怎么样 ?
Map<String, String> params = new HashMap<String, String>() {};
将创建HashMap
派生新类(注意以下括号,您可以在其中放方法,成员等)
您的地图初始化,然后由此宣告了初始化器块:
Map<String, String> params = new HashMap<String, String>() {
{ // here }
};
并在那里你打电话给你的人口方法。
这个成语很好,但你必须知道你正在创建一个新的类,而不仅仅是一个新的对象。
因为这个类是一个内部类,它将有一个隐含的this
指向包含的外部类。您的匿名类由于可从serialisable类派生而成为可串行化的。但是,您的外部类(由this
指针引用)不是。
像XStream
这样的工具,它通过反射串行化为XML,将发现this
指针并尝试对周围的对象进行序列化,这同样令人困惑。
我想补充@布赖恩·阿格纽的回答这个建议:
我有地方,我需要稍微不同的行为了一个对象的情况下,所以我用一个匿名内部类扩展它的功能,你在做例。外部类是一个GUI应用程序,并且我没有将它设置为可序列化的,因为这并不是必需的,所以像@Brian说的那样,没有匿名的内部类可以被序列化,即使它们扩展的类是。
在这种情况下,您只需要定义不同的行为,以便何时反序列化类以及何时再次序列化。如果你有一个特定的构造函数的类,使用这样的方法,在你的类:
public FunctionalObject getNewFunctionalObject (String param1, String param2) {
// Use an anonymous inner class to extend the behavior
return new FunctionalObject (param1, param2) {
{
// Initialization block code here
}
// Extended behavior goes here
};
}
所以,当你反序列化,你可以拨打电话这样的:
FunctionalObject fo = (FunctionalObject) objectInputStream.readObject();
fo = getNewFunctionalObject(fo.getParam1(), fo.getParam2());
序列化时,您将需要创建一个new
对象,该对象是旧对象的克隆。有些类内置了这种行为,而在其他类中则需要专门定义它。对于序列化,如果你有一个构造函数,可以克隆它,或者如果你的类定义了clone
方法,你可以这样做:
objectOutputStream.writeObject (fo.clone());
然后,该对象的clone
将不再是一个参考的匿名内部类,但引用了可序列化的对象的实际副本。
在您的例子的情况下,你可能只是做到了这一点:
// Assuming objectOutputStream has already been defined
Map<String, String> params = new HashMap<String, String>() {{
put("param1", "value1");
put("param2", "value2");
}};
objectOutputStream.writeObject (new HashMap<String,String> (params));
这工作,因为HashMap
类有一个构造函数将返回任何的HashMap
传递到它的克隆。要说简单的话,这是很多的话,但我希望自己早早得到这个建议。
通过'静态初始化程序',你的意思是'实例初始化程序? – 2012-07-31 09:21:40
那么预期的封闭类会是什么? – Shark 2012-07-31 09:22:25
@ Eng.Fouad - 哎呀。修正 – 2012-07-31 09:24:00