Java 序列化时如何保存静态变量
我的目标:我需要在关机后将应用程序状态保持在完全相同的状态,假设它相当于“挂起”状态 我的问题:我确实知道序列化机制不会保存Java 序列化时如何保存静态变量,java,serialization,static-variables,Java,Serialization,Static Variables,我的目标:我需要在关机后将应用程序状态保持在完全相同的状态,假设它相当于“挂起”状态 我的问题:我确实知道序列化机制不会保存瞬态变量,也不会保存静态变量。但是,在应用程序暂停/关闭后,我需要将静态变量保持在完全相同的状态 方法1:我可以使用我的“文件格式”将静态变量的状态保存到不同的文件中,并将对象序列化到不同的文件中 a) 这是“正常”方法吗? 方法2:如果我扩展ObjectInputStream/ObjectOutputStream并覆盖方法readStreamHeader/writeStr
瞬态
变量,也不会保存静态
变量。但是,在应用程序暂停/关闭后,我需要将静态
变量保持在完全相同的状态
方法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_);
}
}
@SuppressWarnings(“串行”)
类SequenceIdentifier实现可序列化
{
受保护的静态长seqIdentifier_u=1L;//不得重置此变量。
private long id_;//要序列化的对象变量。
专用序列标识符(长id)
{id\=id;
}
@凌驾
公共字符串toString()
{return(“+seqIdentifier\”的“+Id\”);
}
公共静态SequenceIdentifier newInstance()
{返回新的SequenceIdentifier(seqIdentifier_U+);
}
}
最后一个类OOStream扩展了ObjectOutputStream
{
公共OOStream(OutputStream out)抛出IOException
{super(out);
}
@凌驾
受保护的void writeStreamHeader()引发IOException
{super.writeLong(SequenceIdentifier.seqIdentifier_u3;);
}
}
最后一个类OIStream扩展了ObjectInputStream
{
公共OIStream(InputStream in)引发IOException
{super(in);
}
@凌驾
受保护的void readStreamHeader()引发IOException
{SequenceIdentifier.seqIdentifier}=super.readLong();
}
}
公共班机
{
公共静态无效转储(ArrayList ID)
{
用于(SequenceIdentifier id:ids)
系统输出打印项次(id);
}
公共静态void saveData()
{
ArrayList ID=新的ArrayList(Arrays.asList(SequenceIdentifier.newInstance(),
SequenceIdentifier.newInstance(),
SequenceIdentifier.newInstance(),
SequenceIdentifier.newInstance());
try(OOStream oOut=newoostream(newfileoutputstream(“foo.bin”))
{oOut.writeObject(id);
}捕获(例外e)
{System.err.println(e);
}
转储(ids);
}
@抑制警告(“未选中”)
公共静态void loadData()
{
ArrayList ID=null;
try(OIStream oIn=newoistream(newfileinputstream(“foo.bin”))
{ids=(ArrayList)oIn.readObject();
}捕获(例外e)
{System.err.println(e);
}
转储(ids);
}
公共静态void main(字符串[]args)
{
saveData();
System.out.println(“此时的计数器”+SequenceIdentifier.SequenceIdentifier_);
SequenceIdentifier.seqIdentifier u0;
loadData();
System.out.println(“此时的计数器”+SequenceIdentifier.SequenceIdentifier_);
}
}
我将创建一个单独的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。有几种可能性
readObect()/writeObject()
方法,分别调用defaultReadObject()
和defaultWriteObject()
,然后对字段进行序列化/反序列化writeReplace()/readResolve()
方法,将包含此成员的代理对象替换为非暂时的非静态的成员
可外部化
,并在相关方法中完全控制序列化过程我刚刚开始了我的java“冒险”,您能举例说明一下解决方案2和3中的含义吗?请看一下java对象序列化规范和java教程中的序列化章节。