java静态变量序列化

Posted

技术标签:

【中文标题】java静态变量序列化【英文标题】:java static variable serialization 【发布时间】:2015-01-13 13:24:41 【问题描述】:

在序列化过程中静态变量的值是如何保持的(如果有的话)。我在堆栈上读过类似的问题,其中说静态变量本质上是瞬态的,即它们的状态或当前值没有序列化。

我只是在做一个非常简单的例子,我序列化一个类并将其保存到一个文件中,然后再次从文件中重建该类。令人惊讶的是,我发现静态变量的值和序列化发生的时间被保存了.

这是怎么发生的。这是因为在序列化过程中保存了类模板及其实例信息。这是代码sn-p -

public class ChildClass implements Serializable, Cloneable

    /**
     * 
     */
    private static final long serialVersionUID = 5041762167843978459L;

    private static int staticState;
    int state = 0;

    public ChildClass(int state)
        this.state = state;
        staticState = 10001;
    

    public String toString() 
        return "state" + state + " " + "static state " + staticState;
    

    public static void setStaticState(int state) 
        staticState = state;
    

这是我的主要课程

public class TestRunner 

    /**
     * @param args
     */
    public static void main(String[] args) 
        new TestRunner().run();
    

    public TestRunner() 

    

    public void run() 
        ChildClass c = new ChildClass(101);
        ChildClass.setStaticState(999999);
        FileOutputStream fo = null;
        ObjectOutputStream os = null;

        File file = new File("F:\\test");
        try 
            fo = new FileOutputStream(file);
            os = new ObjectOutputStream(fo);
            os.writeObject(c);
         catch (IOException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
         finally 

            try 
                if(null != os)os.close();
                if(null != fo) fo.close();
             catch (IOException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            

        


        FileInputStream fi = null;
        ObjectInputStream ois = null;
        ChildClass streamed;

        try 
            fi = new FileInputStream(file);
            ois = new ObjectInputStream(fi);
            Object o = ois.readObject();
            if(o instanceof ChildClass)
                streamed = (ChildClass)o;
                //ChildClass cloned = streamed.clone();
                System.out.println(streamed.toString());
            
         catch (IOException | ClassNotFoundException  e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
         finally 
            try 
                if(null != ois)ois.close();
                if(null != fi) fi.close();
             catch (IOException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            

        
    

注意:代码没有任何问题。我只是想知道如何保存“ChildClass”类中的静态变量“staticState”的值。如果我通过网络传输这个序列化数据,状态会被保存吗

【问题讨论】:

this question 的可能重复项。我没有“重复”这个问题,因为我还不能完全确定这是否是正确的重复。 虽然我的问题与静态变量的序列化有关,但我的问题是关于我注意到的实际上不符合标准文档的行为。 【参考方案1】:

静态字段值未序列化。输出正在打印静态字段的新值,仅仅是因为您将其修改为 999999,但在反序列化之前您从未将其值重置为旧值。由于该字段是静态的,因此新值会反映在ChildClassany 实例中。

要正确断言该字段未序列化,请在反序列化对象之前将值重置为 10001,您会注意到它的值不是 999999。

...
ChildClass.setStaticState(10001);

FileInputStream fi = null;
ObjectInputStream ois = null;
ChildClass streamed;

...
// when de-serializing, the below will print "state101 static state 10001"
System.out.println(streamed.toString());

【讨论】:

这就是我的问题。是否反映了静态变量值的变化,因为我在同一个程序中进行序列化和反序列化,即该类已经在 VM 中加载。如果序列化数据通过网络发送,它会重置为构造函数中设置的值吗?? @Dibzmania 是的,它将重置为旧版本。实际上,这里的新值是因为该类已经加载到 VM 中。 我会得到你的确认 :-) @Dibzmania 只是我这边的一个小修正:实际上,当你反序列化一个对象时,在这种情况下静态字段的值将为零,而不是 10001(即值在构造函数中)。

以上是关于java静态变量序列化的主要内容,如果未能解决你的问题,请参考以下文章

Java序列化之排除被序列化字段(transient/静态变量)

Java的外部类和内部类+静态变量和非静态变量的组合关系

java的枚举类enum,定义静态变量还可以有抽象方法,但枚举类不能被继承

反序列化中的静态变量?

java 静态变量和静态常量

java基础-类和对象详解