Java: неизменяемость и сериализация - PullRequest
5 голосов
/ 06 июля 2011

Когда у меня есть неизменный родительский класс A, который НЕ является окончательным, и другой класс B расширяет его (B является изменяемым), есть ли способ повлиять на неизменность A из-за сериализации?

Я написал небольшую программу для сериализации объекта, изменил его состояние в программе, а затем десериализовал его. Я получил объект обратно в том виде, в котором он был сериализован. Так что мне интересно, есть ли способ изменить неизменность А, сериализовав его?

Ответы [ 3 ]

5 голосов
/ 06 июля 2011

Это зависит от того, что именно вы спрашиваете. Если вы просто хотите получить значение, отличное от того, которое вы вставили, то да, вы можете сделать это с помощью сериализации. Сериализованные данные полностью отделены от экземпляра A, который существует в памяти. Когда Java восстанавливает объект из сериализованных данных, она ничего не знает или не заботится об исходном экземпляре A, который использовался для создания этих данных. Это просто создание структуры данных в памяти на основе схемы, представленной в сериализованной информации.

Так что, если вы хотите изменить то, что вы получите, когда восстанавливаете A, вы можете сделать это, вручную изменив двоичные сериализованные данные. Для этого потребуется хорошее понимание формата сериализации Java, но это, безусловно, можно сделать.

Хотя, если вы спрашиваете, существует ли какой-либо способ изменить исходный экземпляр A через сериализацию (например, чтобы каким-то образом получить тот же объект для изменения значения, не создавая новый экземпляр посредством десериализации), то Ответ - нет, вы не можете. Сериализация просто создает снимок текущего состояния объекта. Десериализация создает новый экземпляр объекта, который полностью отделен от исходного экземпляра. Таким образом, хотя вы можете вручную изменить значение, новый объект с новым значением останется неизменным после десериализации.

И если вы спрашиваете, существует ли способ сериализации экземпляра неизменяемого класса A, а затем десериализации данных как чего-то, что идентифицирует как экземпляр класса A, но оказывается изменчивым, то ответ также нет , Сериализованные данные указывают, какой класс объекта представляется, но само определение класса не сериализуется. Таким образом, вы можете изменить указанный класс так, чтобы вы сериализовали экземпляр A, а затем десериализовали экземпляр изменяемого класса B, но это не то же самое, что вернуть изменяемый экземпляр A.

2 голосов
/ 06 июля 2011

Вы не можете изменить его неизменность (класс все еще будет неизменным), но вы можете изменить его значения, отредактировав сериализованную информацию.

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

В любом случае, если вы собираетесь расширять неизменяемый класс, вы, вероятно, хотите, чтобы ваше расширение также было неизменным - если нет шансов, что вы действительно не хотите расширять класс, возможно, вы просто хотите инкапсулировать его ( есть отношения есть или есть?)

0 голосов
/ 06 июля 2011

Когда вы сериализуете объект, этот объект не изменяется независимо от того, является он неизменным или нет.

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

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

...