Разница статической десериализации в Java в зависимости от того, когда сериализуется объект - PullRequest
0 голосов
/ 02 января 2019

Я пытаюсь выяснить (де /) сериализацию в Java.

Я прочитал, что static переменные не сериализованы.

ДляЧтобы понять это, я привел небольшой пример:

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;

public class SerialDemo {

    private static void writeFile() throws IOException, ClassNotFoundException {
        ObjectOutputStream o=new ObjectOutputStream(new FileOutputStream("foo"));
        Test test = new Test();
        o.writeObject(test);
        o.flush();
    }

    private static Test readFile() throws FileNotFoundException, IOException, ClassNotFoundException {
        ObjectInputStream in=new ObjectInputStream(new FileInputStream("foo"));
        return (Test) in.readObject();
    }
}
class Test implements Serializable{
    static Integer i;
    public Test(){
        i = 10;
    }
}

Почему существуют различия между запуском этих двух основных методов?

Первая версия: Сериализация и десериализация за один запуск

public static void main(String[] args)  {

        try {
            // Serialization
            writeFile();
            // Deserialization
            Test deserializedFile = readFile();
            System.out.println(deserializedFile.i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Это выводит 10.Но почему?Я думал, что значение Integer i не было сериализовано, так как это static.

Вторая версия: Сериализация и десериализация в двух разных запусках.

Если япервый запуск:

public static void main(String[] args)  {
        try {
            // Serialization
            writeFile();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

и во второй запуск:

public static void main(String[] args)  {
        try {
            // Deserialization
            Test deserializedFile = readFile();
            System.out.println(deserializedFile.i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Он выводит null, как я предложил в в первой версии тоже.

В чем разница?!

Ответы [ 3 ]

0 голосов
/ 02 января 2019

Работает как положено.При первом запуске переменная i не сериализуется.То, что вы видите, это значение, которое было установлено в конструкторе Test , и поскольку оно статическое, значение одинаково для всех объектов одного и того же класса.

Во время второго запуска вы не создаетеТестовый класс через конструктор, поэтому значение не установлено.Десериализация не вызывает конструктор Test и не десериализует значение i, поэтому вы видите правильное выходное нулевое значение.

0 голосов
/ 02 января 2019

Простой: это статическая переменная. Он инициализируется в вашем первом примере, когда вы создаете один экземпляр с помощью конструктора!

Во втором примере этот конструктор никогда не вызывается, поле остается пустым!

Это все, что нужно для этого. И, как вы сказали сами: статическое поле не записано в этот файл. В ваших двух примерах важно только то, что одна версия вызывает конструктор, а другая - нет.

Помимо этого, здесь есть еще одно заблуждение: вы пишете deserializedFile.i ... Это концептуально неправильно. Вы должны использовать Test.i взамен. Статические переменные одинаковы для всех экземпляров, их владельцем является класс Test, а не какой-то экземпляр этого класса!

И просто для записи: deserializedFile - очень вводящее в заблуждение имя. Эта переменная представляет десериализованный объект Test. Это не в файл! Имена должны говорить, о чем они, а не лгать. Это имена лгут большое время!

0 голосов
/ 02 января 2019

В вашем первом примере значение 10 по-прежнему находится внутри статической переменной i, поскольку оно находится в том же цикле.На самом деле он не загружается методом readFile().

Во втором примере значение по-прежнему равно 10 в ходе первого запуска, но во втором запуске это значение по умолчанию null (конструктор еще не вызван), вызов readFile() фактически не загружает значения в i.


Попробуйте вызвать deserializedFile.i = null; перед readFile() в первом примере, и вы 'Вы заметите, что происходит то же поведение, что и во втором примере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...