今天写个小的文本处理程序,用到了一个临时类的序列化,在类中加入了一个私有变量后运行总会出现错误
加入的私有变量如下:
private ArrayList
得到的运行结果是:
java.io.NotSerializableException: java.util.HashMap$Entry
真是百思不得其解。Google了半天,发现Tomcat里面有人提到这个问题,原因好像是Session类的什么地方需要修改。这个原因和我的问题真是风马牛不相及。
再仔细查找,最终发现,原来这是Java语言目前存在的一个Bug。原来HashMap对应衍生元素除了Key可以被序列化,其他的如keySet, EntrySet, Values都不能被序列化。当然,HashMap本身还是可以被序列化的。
最后我选择了新建一个ArrayList来将KeySet中的元素转换为String后存放起来,就可以实现我需要的序列化了。
呵呵,我该买彩票啊,随便玩玩居然玩到Java自带的Bug里面去了。这个Bug为什么会存在Java里面呢,而且这个Bug是2002就被发现了啊。Sigh~! Java也不是完美的啊!
详细的sun网站上登记的Bug信息如下:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4756277
Bug ID:
4756277
Votes
7
Synopsis
(coll) HashMap's keySet(), entrySet() and values() are not serializable
Category
java:classes_util
Reported Against
1.3.1
Release Fixed
State
3-Accepted, bug
Priority:
4-Low
Related Bugs
Submit Date
01-OCT-2002
Description
FULL PRODUCT VERSION :
Occurs in both 1.3.0 and 1.3.1:
java version "1.3.0_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0_02)
Java HotSpot(TM) Client VM (build 1.3.0_02, mixed mode)
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
(Service Pack 2)
A DESCRIPTION OF THE PROBLEM :
The collections returned by calls to
java.util.HashMap#entrySet, #keySet and #values are not
Serializable which, although consistent with the
documentation, is confusing and counter-intuitive because
HashMap itself is Serializable.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a HashMap.
2. Attempt to serialize the result of calling keySet(),
entrySet() or values() on that HashMap.
EXPECTED VERSUS ACTUAL BEHAVIOR :
I would (naively, optimistically :-) assume these
collections to be Serializable, since the object from which
they come is itself Serializable.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
keySet():
Trying to serialize [two, one, three]...failed:
java.io.NotSerializableException: java.util.HashMap$1
at java.io.ObjectOutputStream.outputObject(ObjectOutputStream.java:1148)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:366)
at
test.MapCollectionsSerializeMain.trySerialize(MapCollectionsSerializeMain.java:15)
at
test.MapCollectionsSerializeMain.main(MapCollectionsSerializeMain.java:36)
entrySet():
Trying to serialize [two=two, one=one, three=three]...failed:
java.io.NotSerializableException: java.util.HashMap$3
at java.io.ObjectOutputStream.outputObject(ObjectOutputStream.java:1148)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:366)
at
test.MapCollectionsSerializeMain.trySerialize(MapCollectionsSerializeMain.java:15)
at
test.MapCollectionsSerializeMain.main(MapCollectionsSerializeMain.java:38)
values():
Trying to serialize [two, one, three]...failed:
java.io.NotSerializableException: java.util.HashMap$2
at java.io.ObjectOutputStream.outputObject(ObjectOutputStream.java:1148)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:366)
at
test.MapCollectionsSerializeMain.trySerialize(MapCollectionsSerializeMain.java:15)
at
test.MapCollectionsSerializeMain.main(MapCollectionsSerializeMain.java:40)
REPRODUCIBILITY :
This bug can be reproduced rarely.
---------- BEGIN SOURCE ----------
package test;
import java.io.*;
import java.util.*;
public class MapCollectionsSerializeMain
{
private static void trySerialize (Object o) {
try {
ObjectOutputStream stream
= new ObjectOutputStream(new ByteArrayOutputStream());
System.out.print("Trying to serialize " + o + "...");
stream.writeObject(o);
stream.flush();
System.out.println("done");
}
catch (Exception e) {
System.out.print("failed: ");
e.printStackTrace();
}
}
// ----------------------------------------------------------------------
// Entry point
public static void main (String[] args) {
Map map = new HashMap();
map.put("one", "one");
map.put("two", "two");
map.put("three", "three");
System.out.println("keySet():");
trySerialize(map.keySet());
System.out.println("entrySet():");
trySerialize(map.entrySet());
System.out.println("values():");
trySerialize(map.values());
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
For the keySet() and valueSet() cases, one could create a
new HashSet from those sets, but that's inefficient and it
doesn't cover the values() case.
The right answer in the first place is presumably that any
Serializable object which contains a Set (or xxxxx abstract
type not documented as Serializable) must implement its own
readObject and writeObject methods which (de-)serialize the
set manually. Either that, or define the object to contain
a HashSet (or xxxxx type documented as Serializable).
(Review ID: 165184)
======================================================================
Work Around
N/A
Evaluation
N/A
看样子不是java 的bug的问题,是因为你的Entry 类没有实现序列化接口,而之所以转化为String 可以,是英文String类是已经实现序列化接口的。在Entry类实现Comparable接口试试
回复删除