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

Java 静态变量是否在序列化过程中序列化,java,Java,我无意中理解了java序列化。我在许多文档和书籍中读到,静态和瞬态变量不能在Java中序列化。 我们声明一个serialVersionUid,如下所示 private static final long serialVersionUID = 1L; 如果静态变量没有序列化,那么在反序列化过程中,我们经常会遇到异常 java.io.InvalidClassException 从反序列化对象中提取SerialVersionId,并与加载类的SerialVersionId进行比较 据我所知,我认为

我无意中理解了java序列化。我在许多文档和书籍中读到,静态和瞬态变量不能在Java中序列化。 我们声明一个serialVersionUid,如下所示

private static final long serialVersionUID = 1L;
如果静态变量没有序列化,那么在反序列化过程中,我们经常会遇到异常

java.io.InvalidClassException
从反序列化对象中提取SerialVersionId,并与加载类的SerialVersionId进行比较

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


“java中的静态和瞬态变量无法序列化”是一个神话吗。请纠正我的错误,我对这个概念感到困惑。

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

serialVersionUID是一个特殊的静态变量,用于验证本地类是否与用于序列化对象的类兼容。与其他变量一样,它不仅仅是一个静态变量,这些变量肯定不是序列化的

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

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

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

  • 瞬态变量:
    瞬态
    变量未序列化,因此在反序列化过程中,这些变量将使用相应的默认值初始化(例如:对于对象
    null
    int
    0

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


  • 下面的示例解释了静态、实例、瞬态和超类变量序列化及其输出。

    序列化类:

    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
    
    超级类:

    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
    
    序列化和反序列化:

    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
    
    输出:

    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
    

    您可以自己测试—下面是一些示例代码,可以回答您的问题:

    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
    的对象,其中包含一个静态整型字段和一个非静态字段。我们序列化对象,然后在序列化之后增加静态整数


    当我们稍后反序列化对象时,我们看到它的值是递增的,这意味着它没有被序列化。

    在本例中,
    serialVersionUID
    也被序列化

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

    但是,在正常情况下,不会序列化在主类/运行时向静态变量提供值的情况

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

    有关详细信息,请参阅“”


    希望有帮助。干杯

    否,如果类具有静态变量,则在序列化时将跳过该变量。因为静态变量对于所有对象都是唯一的,而序列化仅用于保存对象属性(对象的状态)。
    静态变量是类的属性

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

    比如说,

    案例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
    
      }
    
    }
    
    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
    
      }
    
     }
    
    输出:

    //after deserialization
    
     firstName= abc
    
     lastName= null
    
    案例2:在声明时初始化

    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
    
      }
    
    }
    
    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
    
      }
    
     }
    
    输出:

    //after deserialization
    
     firstName= abc
    
     lastName= null
    
    //反序列化后

    firstName= abc
    
    lastName= pqr
    

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

    特殊静态变量是什么意思?它意味着它是一个特殊的静态变量。(特别是,它在序列化中的处理方式与其他静态变量不同。)它很特殊,因为序列化机制查找此静态变量以了解类的串行版本UID是什么。序列化机制忽略了所有其他静态变量。感谢您给出的精确答案,请欣赏。静态变量属于一个类,而不属于任何单个实例。序列化的概念与对象的当前状态有关。只有与类的特定实例关联的数据才被序列化,因此在序列化过程中会忽略静态成员字段。“因此,在反序列化时,将从类中加载静态变量值。(将加载当前值)。”如果类在另一个JVM中反序列化,该怎么办?@mdev:正确的说法是,
    static
    变量根本不被触及。说“静态变量值将从类加载”到它本身是没有意义的。静态变量不会被序列化,无论它在类初始化期间是否提供了值。您引用的来源和答案都不正确,您的ci