我偶然发现了解java序列化。我在许多文档和书中都读到静态和瞬态变量无法用Java序列化。 我们声明一个serialVersionUid如下。
private static final long serialVersionUID = 1L;
如果静态变量未被序列化,那么在反序列化过程中我们经常会遇到异常。
java.io.InvalidClassException
,其中提取了反序列化对象的serialVersionUID,并与加载的类的serialVersionUID进行比较。
据我所知,我认为如果静态变量无法序列化。这个例外毫无意义。我可能错了,因为我还在学习。
“java中的静态和瞬态变量无法序列化”是一个神话吗?请纠正我,我对这个概念一团糟。
答案 0 :(得分:56)
实例变量:这些变量是序列化的,因此在反序列化过程中我们将返回序列化状态。
静态变量:这些变量未被序列化,因此在反序列化期间,静态变量值将从类中加载。(将加载当前值。)
瞬态变量: transient
变量未序列化,因此在反序列化期间,这些变量将使用相应的默认值进行初始化(例如:对象null
,{ {1}} int
)。
超类变量:如果超类也实现了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)
在声明时已初始化的任何静态变量都将被序列化。