Java-反序列化包含基元类型的哈希表时出错

Java-反序列化包含基元类型的哈希表时出错,java,serialization,hashtable,objectinputstream,objectoutputstream,Java,Serialization,Hashtable,Objectinputstream,Objectoutputstream,我使用ObjectOutputStream序列化了一个HashTable对象。序列化对象时,没有异常,但在反序列化时,会发生以下异常: Exception in thread "main" java.io.InvalidClassException: java.lang.Long; local class incompatible: stream classdesc serialVersionUID = 4290774032661291999, local class serialVersion

我使用
ObjectOutputStream
序列化了一个
HashTable
对象。序列化对象时,没有异常,但在反序列化时,会发生以下异常:

Exception in thread "main" java.io.InvalidClassException: java.lang.Long; local class
incompatible: stream classdesc serialVersionUID = 4290774032661291999, local class
serialVersionUID = 4290774380558885855
当我删除
哈希表
中具有非
字符串
值的所有键时,不再出现错误(我删除的所有键/值对都有一个基元类型作为其值)

是什么导致了这个错误

更新-以下是代码

public static String serialize(Quiz quiz) throws IOException{
    HashMap<String,Object> quizData = new HashMap<String,Object>();
    quizData.put("version", 0); //int
    quizData.put("name", quiz.getName()); //String
    quizData.put("desc", quiz.getDesc()); //String
    quizData.put("timelimitType", quiz.getTimelimitType()); //String
    quizData.put("timelimit", quiz.getTimelimit()); //long
    ArrayList<String> serializedQuestionsData = new ArrayList<String>();
    for (Question question : quiz.getQuestions())
        serializedQuestionsData.add(Question.serialize(question));
    quizData.put("questions", serializedQuestionsData.toArray(new String[0])); //String[]
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos;
    try { oos = new ObjectOutputStream(baos); } catch (IOException error){ throw error; }
    try { oos.writeObject(quizData); } catch (IOException error){ throw error; }
    return baos.toString();
}
@SuppressWarnings("unchecked")
public static Quiz deserialize(String serializedQuizData) throws IOException, ClassNotFoundException{
    ByteArrayInputStream bais = new ByteArrayInputStream(serializedQuizData.getBytes());
    ObjectInputStream ois;
    try { ois = new ObjectInputStream(bais); } catch (IOException error){ throw error; }
    HashMap<String,Object> quizData;
    // Exception occurs on the following line!!
    try { quizData = (HashMap<String,Object>) ois.readObject(); } catch (ClassNotFoundException error){ throw error; }
    Quiz quiz;
    if ((int) quizData.get("version") == 0){
        quiz = new Quiz((String) quizData.get("name"),
                (String) quizData.get("desc"),
                (String) quizData.get("timelimitType"),
                (long) quizData.get("timelimit"));
        for (String serializedQuestionData : (String[]) quizData.get("questions"))
            quiz.addQuestion(Question.deserialize(serializedQuestionData));
    } else {
        throw new UnsupportedOperationException("Unsupported version: \"" + quizData.get("version") + "\"");
    }
    return quiz;
}
公共静态字符串序列化(测验)引发IOException{
HashMap quizData=新的HashMap();
quizData.put(“版本”,0);//int
quizData.put(“name”,quick.getName());//字符串
quizData.put(“desc”,quick.getDesc());//字符串
quizData.put(“timelimitType”,quick.getTimelimitType());//字符串
quizData.put(“timelimit”,quick.getTimelimit());//长
ArrayList serializedQuestionsData=新ArrayList();
for(问题:quick.getQuestions())
serializedQuestionsData.add(问题.序列化(问题));
quizData.put(“questions”,serializedQuestionsData.toArray(新字符串[0]);//字符串[]
ByteArrayOutputStream bas=新的ByteArrayOutputStream();
对象输出流oos;
尝试{oos=newobjectoutputstream(baos);}catch(IOException error){throw error;}
尝试{oos.writeObject(quizData);}catch(IOException error){throw error;}
返回bas.toString();
}
@抑制警告(“未选中”)
公共静态测试反序列化(String serializedQuizData)引发IOException、ClassNotFoundException{
ByteArrayInputStream bais=新的ByteArrayInputStream(serializedQuizData.getBytes());
目的输入流ois;
尝试{ois=newobjectinputstream(bais);}catch(IOException error){throw error;}
HashMap-quizData;
//以下行出现异常!!
尝试{quizData=(HashMap)ois.readObject();}catch(ClassNotFoundException错误){throw error;}
问答游戏;
if((int)quizData.get(“版本”)==0){
测验=新测验((字符串)quizData.get(“名称”),
(字符串)quizData.get(“desc”),
(字符串)quizData.get(“timelimitType”),
(长)quizData.get(“时限”);
for(String serializedQuestionData:(String[])quizData.get(“questions”))
quick.addQuestion(Question.deserialize(serializedQuestionData));
}否则{
抛出新的UnsupportedOperationException(“不支持的版本:\”“+quizData.get(“版本”)+“\”);
}
回访测验;
}

我能想到的唯一解释是,在读写对象流之间,有东西正在破坏对象流。“本地类”(4290774380558885855)中的serialVersionID是所有尝试与Java(tm)兼容的Java实现中的标准版本。
Java.lang.Long
的源代码表示,自Java 1.0.2以来,该串行版本id没有改变


如果需要进一步的帮助,则需要提供一个SSCE,该SSCE涵盖序列化对象的创建和读取。

问题在于,您正在使用
toString()
将字节数组输出流转换为字符串。
toString()
方法仅使用平台默认编码来转换字节(完全不表示字符,但纯粹是二进制数据)转换为字符串。因此,这是一种有损操作,因为平台默认编码并没有为每个可能的字节都指定一个有效字符

不应使用字符串保存二进制数据。字符串包含字符。如果确实需要字符串,请使用十六进制或Base64编码器对字节数组进行编码。否则,只需使用字节数组保存二进制数据:

public static byte[] serialize(Quiz quiz) throws IOException{
    ...
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ...
    return baos.toByteArray();
}

@SuppressWarnings("unchecked")
public static Quiz deserialize(byte[] serializedQuizData) throws IOException, ClassNotFoundException{
    ByteArrayInputStream bais = new ByteArrayInputStream(serializedQuizData);
    ...
    return quiz;
}