2017-09-26 24 views
1

我的目標:我需要在關機後保持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_); 
    } 
} 

回答

2

我會創建一個單獨的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。

0

幾種可能性。

  1. 使之成爲非static
  2. 分別編寫defaultReadObject()defaultWriteObject(),然後序列化/反序列化該字段的方法寫入互補readObect()/writeObject()方法。
  3. 編寫互補writeReplace()/readResolve()將包含此成員的代理對象替換爲非transientstatic成員的方法。
  4. 使對象Externalizable自己在相關的方法中完全控制序列化過程。
  5. 查看您的需求。
+0

我剛剛開始了我的java「冒險」,所以你可以舉例說明我在解決方案2和3中的含義是什麼? –

+0

查看Java對象序列化規範和Java教程的序列化章節。 – EJP