Сериализуются статические переменные в процессе сериализации
Я наткнулся на понимание сериализации Java. Во многих документах и книгах я прочитал, что статические и переходные переменные не могут быть сериализованы в Java.
Мы объявляем serialVersionUid следующим образом.
private static final long serialVersionUID = 1L;
Если статическая переменная не была сериализована, мы часто сталкиваемся с исключением в процессе де-сериализации.
java.io.InvalidClassException
в котором serialVersionUID из десериализованного объекта извлекается и сравнивается с serialVersionUID загруженного класса.
Насколько я знаю, я думаю, что если статические переменные не могут быть сериализованы. Нет такого исключения. Возможно, я ошибаюсь, потому что я все еще участвую.
Это миф о том, что "статические и переходные переменные в java не могут быть сериализованы". Пожалуйста, поправьте меня, я в беспорядке об этой концепции.
Ответы
Ответ 1
serialVersionUID - это специальная статическая переменная, используемая процессом сериализации и десериализации, для проверки совместимости локального класса с классом, используемым для сериализации объекта. Это не просто статическая переменная, как другие, которые определенно не сериализуются.
Когда объект класса впервые сериализуется, дескриптор класса, содержащий, помимо прочего, имя класса и серийный номер UID, записывается в поток. Когда это десериализуется, JVM проверяет, совпадает ли UID последовательной версии, прочитанной из потока, с идентификатором локального класса. Если это не так, он даже не пытается десериализовать объект, потому что знает, что классы несовместимы.
Ответ 2
-
Переменные экземпляра: Эти переменные сериализуются, поэтому во время десериализации мы возвращаем сериализованное состояние.
-
Статические переменные: Эти переменные не сериализуются, поэтому во время десериализации статическое значение переменной будет загружено из класса. (Текущее значение будет загружено.)
-
переходные переменные: transient
переменные не сериализуются, поэтому при десериализации эти переменные будут инициализированы соответствующими значениями по умолчанию (например: для объектов null
, int
0
).
-
Переменные суперкласса: Если суперкласс также реализовал интерфейс Serializable, тогда эти переменные будут сериализованы, иначе он не будет сериализовать переменные суперкласса. и при десериализации JVM будет запускать конструктор по умолчанию в суперклассе и заполняет значения по умолчанию. То же самое произойдет для всех суперклассов.
Ответ 3
serialVersionUID
является особенным и не подпадает под действие этих правил. Внутри сериализационного механизма есть код, который специально обрабатывает это поле для выполнения автоматических проверок версий.
Ответ 4
В этом случае также сериализуется serialVersionUID
.
Сериализуется любая статическая переменная, которая предоставляется во время инициализации класса.
Однако в обычных случаях, когда вы указываете значение статической переменной в главном классе/времени выполнения, не будет сериализовано.
Вы можете попытаться получить доступ к serialVersionUID
, сделав его общедоступным и попытаться получить к нему доступ после десериализации.
Вы можете обратиться к http://javabeginnerstutorial.com/core-java-tutorial/transient-vs-static-variable-java/" для получения дополнительной информации.
Надеюсь, что это поможет. Приветствия!
Ответ 5
Ниже приведен пример статической сериализации семантики, экземпляра, переходного и суперклассов и их выходов.
Сериализованный класс:
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
Ответ 6
Вы можете проверить это сами - вот пример кода, который должен ответить на ваш вопрос:
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
с одним статическим целочисленным полем и одним нестатическим полем. Мы сериализуем объект, затем - после сериализации - увеличиваем статическое целое число.
Когда мы позже десериализовываем объект, мы видим, что он имеет увеличенное значение, подразумевая, что он не был сериализован.
Ответ 7
Нет, если класс имеет статическую переменную, то во время сериализации эта переменная будет пропущена. потому что статическая переменная уникальна для всего объекта, а сериализация используется только для сохранения свойств объекта (состояния объекта).
static variable - свойство класса
Ответ 8
Да, статическая переменная будет сериализована, если она будет инициализирована во время объявления.
Например,
случай 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
Ответ 9
Любая статическая переменная, которая была инициализирована во время объявления, будет сериализована.