Десериализация синглтона в java

Я прохожу через эффективную Java и наткнулся на этот пример.

class Elvis implements Serializable {
    public static final Elvis  inst = new Elvis();
    private Elvis() {
        System.out.println("In elvis constructor ");
    }

    public static Elvis getInstance() {
        return inst;
    }
}

согласно книге, Когда я десериализации, новый объект Элвис должна быть построена, но я вижу, что конструктор не вызывается во время десериализации?

вот мой код, который сериализует и десериализует.

FileOutputStream fos = new FileOutputStream("myserial1.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Elvis e = Elvis.getInstance();
System.out.println(" e = "+e.getInstance());

oos.writeObject(e);

System.out.println("Serialization done.");
FileInputStream fis = new FileInputStream("myserial1.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Elvis el = (Elvis) ois.readObject();
System.out.println(" el = "+el.getInstance());

Я вижу, что e и e1 имеют одну и ту же ссылку, а конструктор вызывается только один раз.

Я неправильно понимаю концепцию здесь?

пожалуйста, помогите.

4 ответов


во время сериализации конструктор не вызывается, поля инициализируются процессом десериализации или readObject() метод (если вы добавите этот метод в свой класс). Если вы хотите реализовать сериализовать синглтон, вы должны добавить readResolve() метод, как он описал здесь.


PS.
Имейте в виду, что getInstance() является статическим методом класса Elvis, Так такие звонки как e.getInstance() и el.getInstance() не равно Elvis.getInstance().


Я неправильно понял концепцию здесь?

вы неправильно поняли, что конструктор создает объект. Нет это не так. Конструктор просто инициализирует объект. Теперь десериализации не нужно вызывать конструктор, поскольку он уже имеет состояние сериализованного объекта, и это то, что он должен предоставить нам.

однако, если в иерархии сериализуемого класса есть некоторый несериализуемый класс, то его конструктор будет вызывается для инициализации состояния в этом классе, так как оно не было сериализовано.

вы можете пройти через Спецификации Сериализации.


According to the book, when i deserialize, a new ELVIS object should be constructed,
but i see the constructor is not called at the time of deserialization?

в первую очередь Object creation and constructor invocation are two separate thing. В обычном сценарии при создании объекта с помощью new объект сайта Сначала создается, а затем вызывается конструктор. Вы можете увидеть байт-коды любого класса java, в котором создается объект.

теперь что касается вашего вопроса, в Serialization объект создается как любой другой объект, и вместо запуска конструктора значения / состояние восстанавливается с помощью reflection. Таким образом, в основном значения считываются из потока (постоянное хранилище-ваш случай) и вводится в объект с помощью отражения.


поскольку операция чтения и записи выполняется в одном экземпляре jvm и класс уже был загружен на операции чтения и статических полей уровня atclass магазин, так вот статическую переменную инст не требуется заново создается public static final Elvis inst = new Elvis();

Так же ссылки возвращаются которые были присоединены с классом level