当我序列化时如何保存静态变量

问题描述:

我的目标:我需要在关机后保持App状态完全相同,可以说它相当于“挂起”状态。当我序列化时如何保存静态变量

我的问题:我确实知道,序列化机制不保存transient变量既不static变量。不过,我需要在应用程序挂起/关闭之后将static变量维持在完全相同的状态。

方法-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_); 
    } 
} 

我会创建一个单独的Memento-class,其中包含所有相关数据作为字段并将其解序列化。

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. 使之成为非static
  2. 分别编写defaultReadObject()defaultWriteObject(),然后序列化/反序列化该字段的方法写入互补readObect()/writeObject()方法。
  3. 编写互补writeReplace()/readResolve()将包含此成员的代理对象替换为非transientstatic成员的方法。
  4. 使对象Externalizable自己在相关的方法中完全控制序列化过程。
  5. 查看您的需求。
+0

我刚刚开始了我的java“冒险”,所以你可以举例说明我在解决方案2和3中的含义是什么? –

+0

查看Java对象序列化规范和Java教程的序列化章节。 – EJP