是否在序列化过程中序列化了静态变量

时间:2012-06-12 16:39:36

标签: java

我偶然发现了解java序列化。我在许多文档和书中都读到静态和瞬态变量无法用Java序列化。  我们声明一个serialVersionUid如下。

private static final long serialVersionUID = 1L;

如果静态变量未被序列化,那么在反序列化过程中我们经常会遇到异常。

java.io.InvalidClassException

,其中提取了反序列化对象的serialVersionUID,并与加载的类的serialVersionUID进行比较。

据我所知,我认为如果静态变量无法序列化。这个例外毫无意义。我可能错了,因为我还在学习。

“java中的静态和瞬态变量无法序列化”是一个神话吗?请纠正我,我对这个概念一团糟。

9 个答案:

答案 0 :(得分:56)

  1. 实例变量:这些变量是序列化的,因此在反序列化过程中我们将返回序列化状态。

  2. 静态变量:这些变量未被序列化,因此在反序列化期间,静态变量值将从类中加载。(将加载当前值。)

  3. 瞬态变量: transient变量未序列化,因此在反序列化期间,这些变量将使用相应的默认值进行初始化(例如:对象null,{ {1}} int)。

  4. 超类变量:如果超类也实现了Serializable接口,那么这些变量将被序列化,否则它将不会序列化超类变量。在反序列化时,JVM将在超类中运行默认构造函数并填充默认值。所有超类都会发生同样的事情。

答案 1 :(得分:45)

serialVersionUID是序列化和反序列化过程使用的特殊静态变量,用于验证本地类是否与用于序列化对象的类兼容。它不仅仅是一个静态变量,而是绝对不是序列化的。

当一个类的对象首次被序列化时,一个类描述符包含类名和串行版本UID,并写入该流。当反序列化时,JVM会检查从流中读取的串行版本UID是否与本地类相同。如果它们不是,它甚至不会尝试反序列化对象,因为它知道类是不兼容的。

答案 2 :(得分:3)

serialVersionUID很特殊,不受这些规则的约束。序列化机制中有代码专门处理此字段以执行自动版本检查。

答案 3 :(得分:1)

在这种情况下,serialVersionUID也会序列化。

在类初始化期间提供值的任何静态变量都是序列化的

但是在正常情况下,您将在主类/运行时为静态变量提供值不会被序列化。

您可以尝试通过将其公开来访问serialVersionUID,并在反序列化后尝试访问它。

您可以参考" http://javabeginnerstutorial.com/core-java-tutorial/transient-vs-static-variable-java/"了解更多信息。

希望有所帮助。干杯!!

答案 4 :(得分:0)

下面的示例解释了静态,实例,瞬态和超类varialbes序列化及其输出。

序列化类

public class SerializeEx extends SuperSerializeEx implements Serializable {

    private static final long serialVersionUID = 1L;
    public static int staticNumber = 1234;
    public int instanceNumber = 1234;

    public SerializeEx() {
        staticNumber = 0;
        instanceNumber = 0;
        System.out.println("---sub class constructor---");
    }

    public SerializeEx(int staticNumber, int instanceNumber, int superNumber) {
        super(superNumber);
        this.staticNumber = staticNumber;
        this.instanceNumber = instanceNumber;
    }
}

超级课程:

public class SuperSerializeEx {

    public int superNumber;

    public SuperSerializeEx() {
        System.out.println("---super class constructor---");
        this.superNumber = 1000;
    }

    public SuperSerializeEx(int superNumber) {
        this.superNumber = superNumber;
    }
}

序列化&反序列化

public class MainSerialization {

    public static void main(String[] args) {
        String fileName = "testing.txt";
        serialize(fileName);
        deSerialize(fileName);
    }

    public static void serialize(String fileName) {
        System.err.println("Serialize.....");
        SerializeEx serializeMe = new SerializeEx(10, 10, 10);
        FileOutputStream fos = null;
        ObjectOutputStream out = null;
        try {
            fos = new FileOutputStream(fileName);
            out = new ObjectOutputStream(fos);
            out.writeObject(serializeMe);
            out.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static void deSerialize(String fileName) {
        System.err.println("DeSerialize.....");
        SerializeEx time = null;
        FileInputStream fis = null;
        ObjectInputStream in = null;
        try {
            fis = new FileInputStream(fileName);
            in = new ObjectInputStream(fis);
            time = (SerializeEx) in.readObject();
            in.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
        System.err.println("Instance Numer = " + time.instanceNumber + " \tStatic Number= " + time.staticNumber + " \t Super Number= " + time.superNumber);
        SerializeEx serializeMe = new SerializeEx(1001, 1001, 1001); //Modifying the static and instnce variables
        System.err.println("Instance Numer = " + time.instanceNumber + " \tStatic Number= " + time.staticNumber + " \t Super Number= " + time.superNumber);
    }
}

<强>输出:

---super class constructor---
Serialize.....
DeSerialize.....
Instance Numer = 10     Static Number= 10      Super Number= 1000
Instance Numer = 10     Static Number= 1001    Super Number= 1000

答案 5 :(得分:0)

您可以自己测试一下 - 这里有一些示例代码可以回答您的问题:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class TestJava implements Serializable{
  public static int k = 10;
  public int j = 5;

  public static void main(String[] args) {

    TestJava tj1= new TestJava();
    TestJava tj2;

        try{ //serialization
            FileOutputStream fos = new FileOutputStream("myclass.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(tj1);
            oos.close();
            fos.close();
            System.out.println("object serielized 1..."+tj1.j);
            System.out.println("object serielized 2..."+tj1.k);
            System.out.println("object serielized 3..."+k);
            k=++k; // 'k' value incrementd after serialization
          } catch(FileNotFoundException fnfe){
             fnfe.printStackTrace();
          } catch(IOException ioex){
             ioex.printStackTrace();
          }

          try{ //deserialization
              FileInputStream fis = new FileInputStream("myclass.ser");
              ObjectInputStream ois = new ObjectInputStream(fis);
              tj2 = (TestJava) ois.readObject();
              ois.close();
              fis.close();
              System.out.println("object DEEEEserielized 1..."+tj2.j);
              System.out.println("object DEEEEserielized 2..."+tj2.k); 
              System.out.println("object DEEEEserielized 3..."+k); 
            // in deserialization 'k' value is shown as incremented. 
            // That means Static varialbe 'K' is not serialized.
            // if 'K' value is serialized then, it has to show old value before incrementd the 'K' value.
            } catch(FileNotFoundException fnfe){
              fnfe.printStackTrace();
            } catch(IOException ioex){
              ioex.printStackTrace();
            } catch(ClassNotFoundException CNFE){
              CNFE.printStackTrace();                   
           }
      }
}

这将输出以下内容:

object serielized 1...5
object serielized 2...10
object serielized 3...10
object DEEEEserielized 1...5
object DEEEEserielized 2...11
object DEEEEserielized 3...11

因此,我们创建了一个类TestJava的对象,其中包含一个静态整数字段和一个非静态字段。我们序列化对象,然后 - 在序列化后 - 增加静态整数。

当我们稍后反序列化对象时,我们看到它具有递增的值,暗示它没有被序列化。

答案 6 :(得分:0)

不,如果一个类有静态变量,那么在序列化时将跳过该变量。因为静态变量对于所有对象都是唯一的,并且序列化仅用于保存对象属性(对象的状态)。 static variable是类

的属性

答案 7 :(得分:0)

,如果在声明时将其初始化,则静态变量将被序列化。

例如,

情况1:,在声明时未进行初始化

class Person implements Serializable{

  public String firstName;

  static  String lastName;  
}

public class Employee {

  public static void main(String[] args) {

      Person p = new Person();
      p.firstName="abc";
      p.lastName="xyz";
      //to do serialization

  }

}

输出:

//after deserialization

 firstName= abc

 lastName= null

情况2:,在声明时进行了初始化

class Person implements Serializable{

  public String firstName=="abc";

  static  String lastName="pqr";  
}

public class Employee {

  public static void main(String[] args) {

      Person p = new Person();
      p.firstName="abc";
      p.lastName="xyz";
      //to do serialization

  }

 }

输出:

//反序列化后

firstName= abc

lastName= pqr

答案 8 :(得分:0)

在声明时已初始化的任何静态变量都将被序列化。