任何人都可以在下面的示例中解释序列化问题。我有两个相同的地图(等于返回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();
}
}
答案 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);
}
}