使用不可序列化的对象序列化 hashmap

Posted

技术标签:

【中文标题】使用不可序列化的对象序列化 hashmap【英文标题】:Serialize hashmap with non-serializable objects 【发布时间】:2014-02-10 21:41:13 【问题描述】:

我如何序列化包含不可序列化对象的哈希映射,在我的例子中是 JavaFX 组件?

final HashMap<String, Button> mapButton = new HashMap<>();
// some for loop adding the components..
try 
     FileOutputStream fileOut = new FileOutputStream("Resources/");
     ObjectOutputStream objStream = new ObjectOutputStream(fileOut);
     objStream.writeObject(mapButton);
     objStream.close();
     fileOut.close();
     System.out.println("Serialized HashMap mapButtons has been stored"
                         + " in /tmp/store");
     catch (IOException i) 
          i.printStackTrace();
    

投掷:

java.io.NotSerializableException: javafx.scene.control.Button

【问题讨论】:

你不能序列化不可序列化的对象。期间。 你看,HashMap 对象本身实际上是可序列化的,只有它包含的对象不是。因此我认为这是可能的。 是的,但是HashMap如何序列化它的项目? 【参考方案1】:

如果你想序列化对象,它们必须是Serializable

由于javafx.scene.control.Button 不可序列化,您必须找到另一种方法将按钮的状态保存在其他位置。例如。通过引入一个保护状态的 memento 类:

public class ButtonMemento implements Serializable 

       private static final long serialVersionUID = 1L;

       private boolean text;

       /*
        * Creates a memento that safes the given button's current state.
        */
       public ButtonMemento(Button button)
             this.text = button.getText();
            // extend to record more properties of the button
       

       /*
        * Used to apply the current mementos state to a button
        */
       public void applyState(Button button)
           button.setText(text);
           // extend to apply more properties to the button
       

ButtonMemento 类是一种保护不可序列化对象状态并在以后恢复它的方法。

final HashMap<String, ButtonMemento> mapButton = new HashMap<>();

for(Button b : buttons)
    String mapKey = ...;
    mapButton.put(mapKey, new ButtonMemento(b));
    

try 
    FileOutputStream fileOut = new FileOutputStream("Resources/");
    ObjectOutputStream objStream = new ObjectOutputStream(fileOut);
    objStream.writeObject(mapButton);
    objStream.close();
    fileOut.close();
    System.out.println("Serialized HashMap mapButtons has been stored"
                     + " in /tmp/store");
 catch (IOException i) 
      i.printStackTrace();

也许您可以实现类似BeanMemento 的东西,它可以存储可序列化的 bean 的属性,因此可以与满足 java bean 规范的每个对象一起使用。

【讨论】:

【参考方案2】:

duplicate

您应该在您的类上实现readObjectwriteObject,以便您可以以自定义方式序列化其对象。

首先,将您的不可序列化字段设为transient。 在writeObject 中,首先在流上调用defaultWriteObject 以存储所有非瞬态字段,然后调用其他方法来序列化不可序列化对象的各个属性。 在readObject 中,首先在流上调用defaultReadObject 以读取所有非瞬态字段,然后调用其他方法(对应于您添加到writeObject 的方法)来反序列化您的不可序列化对象。

我希望这是有道理的。 :-)

【讨论】:

【参考方案3】:

您可以围绕 Button 创建一个可序列化的包装器并在其中实现自定义序列化。您将在 writeObject 中保存按钮属性,读取它们并在 readObject 中重新创建按钮

【讨论】:

以上是关于使用不可序列化的对象序列化 hashmap的主要内容,如果未能解决你的问题,请参考以下文章

怎样对带有不可序列化属性的Java对象进行序列化

为啥案例对象可序列化而案例类不可序列化?

如何将不可序列化的对象传递给意图服务?

任何域对象都应该是不可序列化的吗?

如何将不可解析和不可序列化的对象插入 Bundle

反序列化时需要一个列表,但得到一个带有嵌套对象的类 java.util.HashMap