【问题标题】:Serialize hashmap with non-serializable objects使用不可序列化的对象序列化 hashmap
【发布时间】: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如何序列化它的项目?

标签: java serialization hashmap javafx components


【解决方案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 中重新创建按钮

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-23
        • 1970-01-01
        • 2011-10-29
        • 1970-01-01
        • 2018-04-08
        相关资源
        最近更新 更多