Эффективный элемент Java № 77 - Сериализация одноэлементных объектов. Почему я должен использовать readResolve? - PullRequest
1 голос
/ 22 февраля 2011

Эффективная Java # 77 гласит, что мы должны использовать readResolve для сохранения гарантии Singleton во время сериализации. Они использовали пример.

public class Elvis implements Serializable{
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }

и они предлагают использовать

Если класс Элвиса сделан для реализовать Сериализуемый, достаточно следующего метода readResolve чтобы гарантировать синглтон собственности:

// readResolve for instance control - you can do better!
private Object readResolve() {
// Return the one true Elvis and let the garbage collector
// take care of the Elvis impersonator.
return INSTANCE; }

Этот метод игнорирует десериализованный объект, возвращающий выдающийся экземпляр Элвиса, который был создан, когда класс был инициализируется.

  • Теперь вопрос заключается в сериализация загружает класс снова иметь два экземпляра Элвиса?
  • Если класс загружается только один раз тогда у нас должен быть только один экземпляр Элвиса, так как статический поля не сериализуются и не восстанавливается во время десериализация и
  • Откуда же другой Элвис приходит пример, который сделан право на сбор мусора readResolve (запрещено от избегая десериализации процесс). Это можно объяснить?

Ответы [ 3 ]

4 голосов
/ 22 февраля 2011
  • Класс загружается только один раз (если только вы не копаетесь в загрузчиках классов, но тогда классы на самом деле разные).Десериализация вышеприведенного кода действительно создает новый Elvis.Чтобы избежать этого, вам необходимо использовать последовательный прокси.

  • Хотя существует два Elvis экземпляра, Elvis.INSTANCE указывает только на один.

  • Десериализация создает объект без вызова, выполняя любые конструкторы сериализуемых классов (однако он выполняет конструктор без аргументов наиболее производного несериализуемого базового класса).

(ИКстати, вы не сделали свой класс final, так что даже подкласс может быть десериализован. И, кстати, предложенный вами метод readResolve не будет вызываться для подкласса, поскольку он private.)

1 голос
/ 09 февраля 2012

Я бы предложил создать прокси-класс внутри вашего синглтон-класса для хранения всех ваших переменных. Тогда у вас могут быть функции доступа [getProxyClass () и setProxyClass ()]. Сделайте прокси-класс сериализуемым, затем при переходе к сериализации или десериализации используйте прокси-класс и просто используйте функции доступа для его получения или установки. Если вы сделаете это таким образом, это избавит вас от большого количества беспорядка, связанного с синглтон-классом.

0 голосов
/ 22 февраля 2011
  • Теперь вопрос в том, загружает ли сериализация класс снова, чтобы получить два экземпляра Элвиса?

Создается новый экземпляр Elvis (подражатель), но перегруженный метод readResolve гарантирует, что он не будет возвращен как часть структуры данных, возвращаемой ObjectInputStream.readObject().

Имитатор Элвиса недоступен (или скоро станет недоступным) и собирается мусором.

  • Если класс загружается только один раз, то у нас должен быть только один экземпляр Elvis, поскольку статические поля не сериализуются и не восстанавливаются во время десериализации и

В идеале да. На практике №

  • Откуда поступает другой экземпляр Elvis, который разрешен для сборки мусора readResolve (не допускается выход из процесса десериализации). Это можно объяснить?

Процесс десериализации начинается с создания 2-го Элвиса (имитатора), но метод readResolve гарантирует, что его никто никогда не увидит.

Чтобы понять, как и почему это так, вам нужно понять функцию, которую readResolve() метод выполняет при десериализации, как указано здесь . По сути, когда метод readResolve() возвращает INSTANCE, он говорит: «Где бы вы ни собирались использовать имитатор в графе, который мы строим, используйте вместо этого настоящий Элвис».

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