无法对HashMap进行序列化

3

我正在尝试序列化一个HashMap,但它抛出了NotSerializableException

我将HashMap声明为:

HashMap<String, Profile> profiles = new HashMap<String, Profile>();

这是我的代码:

ObjectOutputStream objectOutput = new ObjectOutputStream(openFileOutput(name, Context.MODE_PRIVATE));
objectOutput.writeObject(profiles);
objectOutput.flush()

Profile.java

import java.io.Serializable;

public class Profile implements Serializable {
    String name;
    String server;
    int port;
    boolean useSSL;
    boolean autoConnect;
    String nick;
    String alterNick;
    String realname;
    String username;
    String serverPass;
    String nickservPass;
    String[] autojoinChannels;
    String[] connectCommands;
}

元素的初始化方式如下所示:
Profile profile = new Profile() {{
    name = "SOMETHING";
    useSSL = false;
    // etc. etc.
}};

日志:

java.io.NotSerializableException: tk.microdroid.microirc.MainActivity
        at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364)
        at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
        at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
        at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
        at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
        at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
        at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
        at java.util.HashMap.writeObject(HashMap.java:1013)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1053)
        at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
        at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
        at tk.microdroid.microirc.MainActivity.saveObject(MainActivity.java:168)
        at tk.microdroid.microirc.MainActivity.saveDefaultProfiles(MainActivity.java:201)
        at tk.microdroid.microirc.MainActivity.checkFirstStartup(MainActivity.java:70)
        at tk.microdroid.microirc.MainActivity.onCreate(MainActivity.java:43)
        at android.app.Activity.performCreate(Activity.java:4465)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1931)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1992)
        at android.app.ActivityThread.access$600(ActivityThread.java:127)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1158)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4448)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:823)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:590)
        at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
        at dalvik.system.NativeStart.main(Native Method)

编辑

  • Profile class is defined in a separate file, not an inner class

  • Here are the saveObject() and loadObject() methods

    public Object loadObject(String name) {
        try {
            ObjectInputStream objectInput = new ObjectInputStream(openFileInput(name));
            Object obj = objectInput.readObject();
            objectInput.close();
            Log.v("loadObject()", "Loading " + name + ".. | Type: " + obj.getClass().getName());
            return obj;
        } catch (Exception e) { Log.e("loadObject()", e.toString()); }
        return null;
    }
    
    public void saveObject(Object obj, String name) {
        try {
            Log.v("saveObject()", "Saving " + name + ".. | Type: " + obj.getClass().getName());
            ObjectOutputStream objectOutput = new ObjectOutputStream(openFileOutput(name, MODE_PRIVATE));
            objectOutput.writeObject(obj);
            objectOutput.flush();
            objectOutput.close();
        } catch (Exception e) { Log.e("saveObject()","Error", e); }
    }
    

1
你如何编写HashMap? - Blackbelt
通过 objectOutput#writeObject(profiles) 将 @Blackbelt 写入流中,然后刷新该流。 - OverCoder
1
我真的很想知道为什么这个问题被踩了,我就是不明白。 - OverCoder
1
你能发布saveObject方法吗? - Blackbelt
1
你确定Profile不是 MainActivity 的内部类吗?如果是,它需要被声明为 static。否则,我不明白序列化框架为什么会尝试序列化 MainActivity。请尝试发布更多 MainActivity 代码……包括 saveObject 函数。 - Barett
显示剩余2条评论
2个回答

13

最终,我成功解决了我的问题。

我将对象变量设置为:

Profile profile = new Profile() {{
    name = "SOMETHING";
    useSSL = false;
    // etc. etc.
}};

所以我尝试设置变量时没有使用双括号,像这样:

profile.name = " SOMETHING";
profile.useSSL = false;
// etc. etc.

我甚至不确定为什么会出现这个问题,但最终我已经解决了它。


15
创建了一个内部类,并且该内部类引用了其外部对象,但该外部对象没有实现可序列化,因此导致了问题。 - user207421
4
使用双括号实际上是Profile的匿名内部子类,即profile不再严格属于Profile类型。而且,它是一个非静态内部类,因此它具有对其封闭对象的引用,而这个引用是不可序列化的。 - SilentICE
1
是的,这种实例化模式通常是一种反模式;你应该避免使用它。我在几个地方看到过它被称为“巧妙的技巧”,但你通常应该将其视为仅仅是一个巧妙的技巧,不适用于真正的代码(因为棘手的代码往往会导致棘手的错误)。 - yshavit

3
如果Profile是MainActivity的嵌套类,请将其声明为静态。 (此外,我不知道为什么序列化框架会尝试序列化MainActivity。)如果不是这种情况,请在包括saveObject在内的MainActivity中发布更多代码,我们将更新答案。
非静态嵌套类具有对其容器类的隐式引用。因此,序列化框架将尝试序列化您的MainActivity。

1
“非静态内部”是一个重言式。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接