我序列化

时间:2017-09-26 11:28:19

标签: java serialization static-variables

我的目标:我需要在关机后将应用状态保持在同一状态,让我们说它相当于"暂停"状态。

我的问题:我知道序列化机制不会transient个变量保存static变量。但是,我需要在App暂停/关闭后将static变量保持在完全相同的状态。

Approach-1 :我可以使用我的"文件格式"将静态变量的状态保存到不同的文件中,并将对象序列化为另一个。

a)这是"正常"方法?

方法-2 :如果我延长ObjectInputStream / ObjectOutputStream并覆盖方法readStreamHeader / writeStreamHeader我可以写任何我想要的内容。所以我也可以写我的静态变量。

b)我在做一些我不应该做的事情吗?

这是我编写的测试方法-2的代码,并且接缝工作正常。请注意,我不是Java程序员,因此了解最佳实践非常重要,如果在这种特殊情况下有任何原因。

@SuppressWarnings("serial")
class SequenceIdentifier implements Serializable
{
    protected static long seqIdentifier_ = 1L;  //This variable MUST NOT be reseted.
    private long id_; //Object variable to be serialised.

    private SequenceIdentifier(long id)     
    {   id_ = id;
    }
    @Override
    public String toString()
    {   return ("Id : " + id_ + " of " + seqIdentifier_);
    }
    public static SequenceIdentifier newInstance()
    {   return new SequenceIdentifier(seqIdentifier_++);
    }   
}

final class OOStream extends ObjectOutputStream 
{
    public OOStream(OutputStream out) throws IOException
    {   super(out);
    }   
    @Override
    protected void writeStreamHeader() throws IOException
    {   super.writeLong(SequenceIdentifier.seqIdentifier_);
    }
}

final class OIStream extends ObjectInputStream 
{
    public OIStream(InputStream in) throws IOException
    {   super(in);
    }
    @Override
    protected void readStreamHeader() throws IOException 
    {   SequenceIdentifier.seqIdentifier_ = super.readLong();
    }
}

public class Main
{
    public static void dump(ArrayList<SequenceIdentifier> ids)
    {
        for (SequenceIdentifier id : ids)
            System.out.println(id);
    }

    public static void saveData()
    {
        ArrayList<SequenceIdentifier> ids = new ArrayList<>(Arrays.asList(SequenceIdentifier.newInstance(),
                                                                                            SequenceIdentifier.newInstance(),
                                                                                            SequenceIdentifier.newInstance(),
                                                                                            SequenceIdentifier.newInstance()));
        try (OOStream oOut = new OOStream(new FileOutputStream("foo.bin")))
        {   oOut.writeObject(ids);
        } catch (Exception e)
        {   System.err.println(e);
        }       
        dump(ids);
    }

    @SuppressWarnings("unchecked")
    public static void loadData()
    {
        ArrayList<SequenceIdentifier> ids = null;
        try (OIStream oIn = new OIStream(new FileInputStream("foo.bin")))
        {   ids = (ArrayList<SequenceIdentifier>)oIn.readObject(); 
        } catch (Exception e)
        {   System.err.println(e);
        }       
        dump(ids);
    }

    public static void main(String[] args)
    {
        saveData();
        System.out.println("Counter at this point " + SequenceIdentifier.seqIdentifier_);

        SequenceIdentifier.seqIdentifier_ = 0;
        loadData();
        System.out.println("Counter at this point " + SequenceIdentifier.seqIdentifier_);
    }
}

2 个答案:

答案 0 :(得分:2)

我会创建一个单独的Memento类,其中包含所有相关数据作为字段并对其进行去序列化。

class MyClassWithStaticFields1 {
    private static String field;
}
class MyClassWithStaticFields2 {
    private static String field;
}

class StaticMemento {
    String field1;
    String field2;
}

// serialization
StaticMemento mem = new StaticMemento();
mem.field1 = MyClassWithStaticFields1.field;
mem.field2 = MyClassWithStaticFields2.field;
outputStream.writeObject(mem);

// deserialize
StaticMemento mem = outputStream.readObject();
MyClassWithStaticFields1.setField(mem.field1);
MyClassWithStaticFields2.setField(mem.field2);

所以基本上你的方法-1。

答案 1 :(得分:0)

几种可能性。

  1. 使其成为非static
  2. 编写分别调用readObect()/writeObject()defaultReadObject()的补充defaultWriteObject()方法,然后序列化/反序列化该字段。
  3. 编写补充writeReplace()/readResolve()方法,将包含此成员的代理对象替换为非transientstatic成员。
  4. 创建对象Externalizable并在相关方法中自行完全控制序列化过程。
  5. 检讨您的要求。