当我序列化时如何保存静态变量
问题描述:
我的目标:我需要在关机后保持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。
答
几种可能性。
- 使之成为非
static
。 - 分别编写
defaultReadObject()
和defaultWriteObject()
,然后序列化/反序列化该字段的方法写入互补readObect()/writeObject()
方法。 - 编写互补
writeReplace()/readResolve()
将包含此成员的代理对象替换为非transient
非static
成员的方法。 - 使对象
Externalizable
自己在相关的方法中完全控制序列化过程。 - 查看您的需求。
我刚刚开始了我的java“冒险”,所以你可以举例说明我在解决方案2和3中的含义是什么? –
查看Java对象序列化规范和Java教程的序列化章节。 – EJP