В этой статье описывается сериализация объекта и десериализация в Java. Поделитесь этим для всех для вашей ссылки. Детали следующие:
1. Введение
Сериализация объекта относится к процессу преобразования объекта в последовательность байтов, в то время как десериализация является процессом восстановления объекта на основе последовательности байтов.
Сериализация обычно используется в следующих сценариях:
1. Сохраните объект навсегда и сохраните байтовую последовательность объекта в локальном файле;
2. Пропустить объекты в сети, сериализовать их;
3. Пропустите объекты между процессами посредством сериализации.
Класс, к которому принадлежит объект, должен реализовать сериализуемый или экстерный интерфейс, который будет сериализован. Для классов, которые реализуют сериализуемый интерфейс, сериализация и десериализация принимают метод сериализации по умолчанию.
Java.io.objectOutputStream представляет выходной поток объекта, а его метод writeObject (Object obj) может реализовать сериализацию объекта и записать полученную байтовую последовательность в целевой выходной поток.
Java.io.objectInputStream представляет поток ввода объекта, а его метод ReadObject () может считывать последовательность байтов из источника входного потока, десериализуйте его в объект и возвращать его.
2. Несколько способов сериализации
Предположим, что класс клиента определяется в зависимости от метода сериализации клиента, могут быть следующие методы сериализации:
1. Реализуемые методы сериализации, неопределенные методы ReadObject и WriteObject
ObjectOutputStream использует JDK для сериализации переменных экземпляров, не связанных с транспортировкой, по умолчанию;
ObjectInputStream Deserialize не транслирует переменные экземпляра объекта клиента с использованием метода по умолчанию JDK.
2. Реализуйте сериализуемые и определяйте методы ReadObject и WriteObject
ObjectOutputStream вызывает метод writeObject (objectOutputStream) класса клиента, чтобы сериализовать переменные экземпляра без транспорта в объекте клиента;
ObjectInputStream вызывает метод readObject (ObjectInputStream) класса клиента, чтобы десериализовать неверностные переменные экземпляра объекта клиента.
3. Реализовать, определяйте методы ReadExternal и WriteExternal
ObjectOutputStream вызывает метод writeExternal класса клиента, чтобы сериализовать переменные без транспортного экземпляра объекта клиента;
ObjectInputStream Сначала создает объект через конструктор без параметра класса клиента, а затем десериализует переменную экземпляра без транспорта объекта клиента с помощью метода ReadExternal.
3. сериализуемый интерфейс
Класс позволяет свою функциональность сериализации, внедряя интерфейс Java.io.iserializable. Классы, которые не реализуют этот интерфейс, не смогут сериализовать или десериализовать любое из их состояний. Все подтипы сериализуемого класса сами по себе сериализуются. Интерфейс сериализации не имеет методов или полей и используется только для определения сериализуемой семантики.
В ходе процесса пустыня поля не сериализованного класса будут инициализированы с использованием общего или защищенного конструктора без параметра в классе. Сериализуемый подкласс должен быть в состоянии получить доступ к конструктору без параметра. Поля, которые могут быть сериализуемыми подклассами, будут восстановлены из потока.
При прохождении представления класса вы можете встретить объекты, которые не поддерживают сериализуемый интерфейс. В этом случае выброшен NotSerializableException, и класс, который не является сериализуемым, идентифицируется.
1. Точная подпись
Классы, которые требуют специальной обработки во время сериализации и десериализации, должны реализовать специальные методы, используя следующие точные подписи:
private void writebject (java.io.objectOutputStream Out) бросает ioException
private void readObject (java.io.objectInputStream In) бросает ioException, classnotfoundexception;
private void readObjectNodata () бросает ObjectStreamException;
Метод WriteBject отвечает за написание состояния объекта конкретного класса, чтобы соответствующий метод ReadObject мог его восстановить. Механизм по умолчанию для сохранения полей объекта можно вызвать путем вызова. DefaultWriteObject. Сам метод не должен вовлекать состояния, принадлежащие к его суперклассу или подклассу. Состояние можно сохранить, написав отдельные поля в ObjectOutputStream с использованием метода writeObject или с использованием метода, поддерживаемого DataOutput для основных типов данных.
Метод ReadObject отвечает за чтение и восстановление полей классов из потока. Он может вызвать в. Метод DefaulTreadObject использует информацию в потоке для распределения полей объектов в потоке, которые сохраняются через соответствующие указанные поля в текущем объекте. Это используется для борьбы с ситуациями, когда новые поля должны быть добавлены после эволюции класса. Сам метод не должен вовлекать состояния, принадлежащие к его суперклассу или подклассу. Состояние можно сохранить, написав отдельные поля в ObjectOutputStream с использованием метода writeObject или с использованием метода, поддерживаемого DataOutput для основных типов данных.
В случае, когда поток сериализации не указал данный класс в качестве суперкласса, который должен быть опустошен, метод ReadObjectNodata отвечает за инициализацию состояния объекта конкретного класса. Это происходит, когда класс десериализованного экземпляра, используемый приемником, отличается от отправителя, а класс, расширенный версией приемника, не является классом, расширенным версией отправителя. Это также происходит, когда поток сериализации был подделан;
При написании объектов в потоку необходимо указать сериализуемый класс альтернативного объекта, который будет использоваться, и вы должны реализовать этот специальный метод с точной подписью:
Any-Access-Modifier Object PriseReplace () бросает ObjectStreamException;
Этот метод записи будет вызвана сериализацией, при условии, что если этот метод существует, и к нему можно получить доступ методом, определенным в классе сериализованного объекта. Следовательно, метод может иметь частный, защищенный и пакетный доступ. Доступ подкласса к этому методу следует правилам доступа Java.
При чтении экземпляра класса из потока вам необходимо указать точную подпись, которую альтернативный класс должен использовать для реализации этого специального метода.
Any-Access-Modifier объекта readResolve () бросает ObjectStreamException;
Этот метод ReadResolve следует тем же правилам вызовов и правилам доступа, что и WriteReplace.
Если класс определяет метод ReadResolve, то метод ReadResolve будет вызван в конце десериализации, а объект, возвращаемый методом, является конечным результатом десериализации.
2. SerialVersionUid
Время выполнения сериализации использует номер версии, называемый Serialversionuid для ассоциации с каждым сериализуемым классом, который используется во время десериализации, чтобы убедиться, что отправитель и приемник сериализованного объекта, загруженный для объекта. Если приемник загружает сериал -версию класса объекта, отличный от соответствующего номера версии отправителя, десериализация приведет к неволю Сериализуемый класс может явно объявить о своем собственном сериал -версии, объявив поле с именем «serialversionuid» (это поле должно быть статическим, окончательным длинным полем):
Any-Access-Modifier Static Long Long SerialVersionUID = 42L;
Если сериализуемый класс явно не объявляет SerialVersionUID, время выполнения сериализации вычисляет значение серийного класса по умолчанию на основе различных аспектов класса, как описано в спецификации сериализации объекта Java (TM) ». Тем не менее, настоятельно рекомендуется, чтобы все сериализуемые классы явно заявляли о значениях SerialVersionUID, поскольку расчет серийного по умолчанию очень чувствителен к деталям класса и может сильно варьироваться в зависимости от реализации компилятора, поэтому в процессе десериализации неожиданного инваалида. может результат. Следовательно, чтобы обеспечить согласованность между значениями serialversionuid в различных компиляторах Java, сериализованный класс должен объявить явное значение SerialVersionUid. Также настоятельно рекомендуется использовать частный модификатор для отображения объявления Serialversionuid, если это возможно, потому что такие объявления используются только для непосредственного объявления класса - поле Serialversionionuid в качестве унаследованного элемента бесполезно. Классы массивов не могут объявить явную серийную версию, поэтому они всегда имеют рассчитанное значение по умолчанию, но классы массива не соответствуют требованиям к значению SerialVersionUID.
3. Экстернализируемый интерфейс
Extraizable - это расширение Serailizable.
Вызовите метод класса WriteExternal во время сериализации и десериализуйте метод ReadExternal;
При выполнении десериализации конструктор класса без параметра, который называется деессериализацией по умолчанию.
Четвертое, резюме
Если метод сериализации по умолчанию принят, если класс реализует сериализуемый интерфейс, его экземпляр может быть сериализован. Как правило, классы, разработанные специально для наследования, должны пытаться не реализовать сериализуемый интерфейс, потому что после того, как родительский класс реализует сериализуемый интерфейс, все его подклассы являются сериализуемыми.
Недостатки метода сериализации по умолчанию:
1. Небезопасно непосредственно сериализовать конфиденциальные данные, которые не подходят для раскрытия объекта;
2. Он не будет проверять, соответствуют ли переменные элемента объекта правильные ограничения и могут быть подделаны данными и вызвать ненормальную работу;
3. Требуется рекурсивное обход объектного графика.
4. Сделайте интерфейс класса, ограниченный внутренней реализацией класса, ограничивая обновление и обслуживание класса.
Внедряя частного типа writebject () и readobject () сериализуемого интерфейса, или реализуя внешний интерфейс, реализуя методы writeexternal () и readexternal () и предоставление конструктора без параметрического типа. может эффективно избежать недостатков метода сериализации по умолчанию.
Есть надежда, что эта статья полезна для дизайна программы Java каждого.