Spec-Zone .ru
спецификации, руководства, описания, API
|
СОДЕРЖАНИЕ | ПРЕДЫДУЩИЙ | NEXT | Спецификация Сериализации Объекта Java версия 6.0 |
ГЛАВА 3 |
Темы:
ObjectInputStream
реализации возражают десериализации. Это поддерживает состояние потока включая набор объектов, уже десериализованных. Его методы позволяют типы примитивов, и возражает, чтобы быть считанным из потока, записанного ObjectOutputStream
. Это управляет восстановлением объекта и объектов, к которым это обращается от потока.package java.io; public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants { public ObjectInputStream(InputStream in) throws StreamCorruptedException, IOException;
public final Object readObject() throws OptionalDataException, ClassNotFoundException, IOException; public Object readUnshared() throws OptionalDataException, ClassNotFoundException, IOException; public void defaultReadObject() throws IOException, ClassNotFoundException, NotActiveException; public GetField readFields() throws IOException; public synchronized void registerValidation( ObjectInputValidation obj, int prio) throws NotActiveException, InvalidObjectException; protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException; protected Class resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException; protected Object resolveObject(Object obj) throws IOException; protected boolean enableResolveObject(boolean enable) throws SecurityException; protected void readStreamHeader() throws IOException, StreamCorruptedException; public int read() throws IOException; public int read(byte[] data, int offset, int length) throws IOException public int available() throws IOException; public void close() throws IOException; public boolean readBoolean() throws IOException; public byte readByte() throws IOException; public int readUnsignedByte() throws IOException; public short readShort() throws IOException; public int readUnsignedShort() throws IOException; public char readChar() throws IOException; public int readInt() throws IOException; public long readLong() throws IOException; public float readFloat() throws IOException; public double readDouble() throws IOException; public void readFully(byte[] data) throws IOException; public void readFully(byte[] data, int offset, int size) throws IOException; public int skipBytes(int len) throws IOException; public String readLine() throws IOException; public String readUTF() throws IOException; // Class to provide access to serializable fields. static abstract public class GetField { public ObjectStreamClass getObjectStreamClass(); public boolean defaulted(String name) throws IOException, IllegalArgumentException; public char get(String name, char default) throws IOException, IllegalArgumentException; public boolean get(String name, boolean default) throws IOException, IllegalArgumentException; public byte get(String name, byte default) throws IOException, IllegalArgumentException; public short get(String name, short default) throws IOException, IllegalArgumentException; public int get(String name, int default) throws IOException, IllegalArgumentException; public long get(String name, long default) throws IOException, IllegalArgumentException; public float get(String name, float default) throws IOException, IllegalArgumentException; public double get(String name, double default) throws IOException, IllegalArgumentException; public Object get(String name, Object default) throws IOException, IllegalArgumentException; } protected ObjectInputStream() throws StreamCorruptedException, IOException; protected readObjectOverride() throws OptionalDataException, ClassNotFoundException, IOException; }
Единственный параметр ObjectInputStream
конструктор требует InputStream
. Вызовы конструктора readStreamHeader
читать и проверяет заголовок и версию, записанную соответствием ObjectOutputStream.writeStreamHeader
метод. Если менеджер безопасности устанавливается, этот конструктор проверки на "enableSubclassImplementation"
SerializablePermission
когда вызвано прямо или косвенно конструктором подкласса, который переопределяет readFields
и/или readUnshared
методы.
ObjectInputStream
блоки конструктора, пока это не завершает чтение потокового заголовка сериализации. Код, который ожидает ObjectInputStream
быть созданным прежде, чем создать соответствие ObjectOutputStream
поскольку тот поток будет мертвая блокировка, начиная с ObjectInputStream
конструктор блокирует, пока заголовок не пишется потоку, и заголовок не будет записан потоку до ObjectOutputStream
конструктор выполняется. Эта проблема может быть разрешена, создавая ObjectOutputStream
перед ObjectInputStream
, или иначе удаляя зависимость от синхронизации между завершением ObjectInputStream
конструкция и создание ObjectOutputStream
. readObject
метод используется, чтобы десериализовать объект от потока. Это читает из потока, чтобы восстановить объект.1. | Если ObjectInputStream подкласс переопределяет реализацию, вызовите readObjectOverride метод и возврат. Перереализация описывается в конце этого раздела. |
2. | Если блочная запись данных происходит в потоке, бросок a BlockDataException с числом доступных байтов. |
3. | Если объект в потоке является нулем, возвратите нуль. |
4. | Если объект в потоке является дескриптором к предыдущему объекту, возвратите объект. |
5. | Если объект в потоке является a Class , считайте ObjectStreamClass дескриптор, добавляют это и его дескриптор к набору известных объектов, и возвращают соответствие Class объект. |
6. | Если объект в потоке ObjectStreamClass , читайте в его данных согласно форматам, описанным в разделе 4.3. Добавьте это и его дескриптор к набору известных объектов. В версиях 1.3 и позже Java 2 SDK, Standard Edition, readClassDescriptor метод вызывают, чтобы читать в ObjectStreamClass если это представляет класс, который не является динамическим прокси-классом, как обозначено в потоковых данных. Если дескриптор класса представляет динамический прокси-класс, вызовите resolveProxyClass метод на потоке, чтобы получить локальный класс для дескриптора; иначе, вызовите resolveClass метод на потоке, чтобы получить локальный класс. Если класс не может быть разрешен, бросьте ClassNotFoundException. Возвратите получающееся ObjectStreamClass объект. |
7. | Если объект в потоке является a String , считайте его информацию о длине, сопровождаемую содержанием строки, закодированной в измененном UTF-8. Для получения дополнительной информации отнеситесь, чтобы Разделить 6.2, "Потоковые Элементы". Добавьте String и его дескриптор к набору известных объектов, и продолжается к Шагу 12. |
8. | Если объект в потоке является массивом, считайте ObjectStreamClass и длина массива. Выделите массив, и добавьте это и его дескриптор в наборе известных объектов. Считайте каждый элемент, используя соответствующий метод для его типа и присвойте это массиву. Продолжите к Шагу 12. |
9. | Если объект в потоке является перечислимой константой, считайте ObjectStreamClass и перечислимое постоянное имя. Если ObjectStreamClass представляет класс, который не является перечислимым типом, InvalidClassException бросается. Получите ссылку на перечислимую константу, вызывая java.lang.Enum.valueOf метод, передавая перечислимый тип, связанный с полученным ObjectStreamClass наряду с полученным именем как параметры. Если valueOf метод бросает IllegalArgumentException , InvalidObjectException бросается с IllegalArgumentException как его причина. Добавьте перечислимую константу и ее дескриптор в наборе известных объектов, и продолжите к Шагу 12. |
10. | Для всех других объектов, ObjectStreamClass из объекта читается из потока. Локальный класс для этого ObjectStreamClass получается. Класс должен быть сериализуемым или externalizable, и не должен быть перечислимым типом. Если класс не удовлетворяет эти критерии, InvalidClassException бросается. |
11. | Экземпляр класса выделяется. Экземпляр и его дескриптор добавляются к набору известных объектов. Содержание, восстановленное соответственно: |
a. | Для сериализуемых объектов выполняется конструктор без аргументов для первого несериализуемого супертипа. Для сериализуемых классов поля инициализируются к значению по умолчанию, подходящему для его типа. Затем поля каждого класса восстанавливаются, вызывая специфичный для класса readObject методы, или если они не определяются, вызывая defaultReadObject метод. Отметьте, что полевые инициализаторы и конструкторы не выполняются для сериализуемых классов во время десериализации. В нормальном случае версия класса, который записал поток, будет тем же самым как классом, читая поток. В этом случае все супертипы объекта в потоке будут соответствовать супертипы в загруженном в настоящий момент классе. Если у версии класса, который записал поток, были различные супертипы чем загруженный класс, ObjectInputStream должно быть более осторожным относительно восстановления или инициализации состояния отличающихся классов. Это должно ступить через классы, соответствуя доступные данные в потоке с классами восстанавливаемого объекта. Данные для классов, которые происходят в потоке, но не происходят в объекте, отбрасываются. Для классов, которые происходят в объекте, но не в потоке, поля класса устанавливаются в значения по умолчанию сериализацией по умолчанию. |
b. | Для объектов externalizable конструктор без аргументов для класса выполняется и затем readExternal метод вызывают, чтобы восстановить содержание объекта. |
12. | Обработайте потенциальные замены классом объекта и/или подклассом ObjectInputStream : |
a. | Если класс объекта не является перечислимым типом и определяет соответствующее readResolve метод, метод вызывают, чтобы позволить объекту заменить себя. |
b. | Затем если ранее включено enableResolveObject, resolveObject метод вызывают, чтобы позволить подклассам потока исследовать и заменять объект. Если предыдущий шаг действительно заменял исходный объект, resolveObject метод вызывают с заменяющим объектом. |
Если замена имела место, таблица известных объектов обновляется так, заменяющий объект связывается с дескриптором. Заменяющий объект тогда возвращается из readObject . |
Все методы для того, чтобы считать примитивы вводят, только используют байты из блочных записей данных в потоке. Если чтение для примитивных данных происходит, когда следующий элемент в потоке является объектом, методы чтения возвращаются-1 или EOFException
как соответствующий. Значение типа примитива читается a DataInputStream
из блочной записи данных.
Когда маркер сброса происходит в потоке, все состояние потока отбрасывается. Набор известных объектов очищается.
Когда маркер исключения происходит в потоке, исключение читается и новое WriteAbortedException
бросается с завершающимся исключением как параметр. Потоковый контекст сбрасывается как описано ранее.
readUnshared
метод используется, чтобы считать "неразделенные" объекты из потока. Этот метод идентичен readObject
, за исключением того, что это предотвращает последующие звонки readObject
и readUnshared
от возврата дополнительных ссылок на десериализованный экземпляр, возвращенный исходным звонком readUnshared
. Определенно:
readUnshared
вызывается, чтобы десериализовать обратную ссылку (потоковое представление объекта, который был записан ранее потоку), ObjectStreamException
будет брошен. readUnshared
возвраты успешно, тогда любые последующие попытки десериализовать обратные ссылки на потоковый дескриптор, десериализованный readUnshared
вызовет ObjectStreamException
быть брошенным. readUnshared
лишает законной силы потоковый дескриптор, связанный с возвращенным объектом. Отметьте, что это сам по себе не всегда гарантирует что ссылка, возвращенная readUnshared
уникально; десериализованный объект может определить a readResolve
метод, который возвращает объект, видимый другим сторонам, или readUnshared
может возвратить a Class
возразите или перечислимая константа, доступная в другом месте в потоке или через внешние средства. Если десериализованный объект определяет a readResolve
метод и вызов того метода возвращают массив, тогда readUnshared
возвращает мелкого клона того массива; это гарантирует, что возвращенный объект массива уникален и не может быть получен во второй раз из вызова readObject
или readUnshared
на ObjectInputStream
, даже если базовым потоком данных управляли.
defaultReadObject
метод используется, чтобы считать поля и объект от потока. Это использует дескриптор класса в потоке, чтобы считать поля в каноническом порядке по имени и типе от потока. Значения присваиваются соответствующим полям по имени в текущем классе. Детали механизма управления версиями могут быть найдены в Разделе 5.5, "Совместимое Развитие Типа Java." Любое поле объекта, который не появляется в потоке, устанавливается в его значение по умолчанию. Отбрасываются значения, которые появляются в потоке, но не в объекте. Это происходит прежде всего, когда более поздняя версия класса записала дополнительные поля, которые не происходят в более ранней версии. Этот метод можно только вызвать от readObject
метод, восстанавливая поля класса. Когда вызвано в любое другое время, NotActiveException
бросается.
readFields
метод читает значения сериализуемых полей от потока и делает их доступными через GetField
класс. readFields
метод является только вызываемым изнутри readObject
метод сериализуемого класса. Это нельзя вызвать не раз или если defaultReadObject
был вызван. GetFields
возразите использует текущий объект ObjectStreamClass
проверять поля, которые могут быть получены для этого класса. GetFields
объект, возвращенный readFields
только допустимо во время этого звонка в классы readObject
метод. Поля могут быть получены в любом порядке. Дополнительные данные могут только быть считаны непосредственно из потока после readFields
был вызван.
registerValidation
метод можно вызвать, чтобы запросить обратный вызов, когда весь график был восстановлен, но прежде, чем объект будет возвращен к исходной вызывающей стороне readObject
. Порядок проверяет обратных вызовов, может управляться, используя приоритет. Обратные вызовы, зарегистрированные в более высоких значениях, вызывают перед теми с нижними значениями. Объект, который будет проверен, должен поддерживать ObjectInputValidation
соедините интерфейсом и реализуйте validateObject
метод. Это только корректно, чтобы зарегистрировать проверки допустимости во время звонка в класс readObject
метод. Иначе, a NotActiveException
бросается. Если объект обратного вызова, предоставленный registerValidation
нуль, InvalidObjectException
бросается.
Запускаясь с SDK Java, Standard Edition, v1.3, readClassDescriptor
метод используется, чтобы читать всего ObjectStreamClass
объекты. readClassDescriptor
вызывается когда ObjectInputStream
ожидает дескриптор класса как следующий элемент в потоке сериализации. Подклассы ObjectInputStream
может переопределить этот метод, чтобы читать в дескрипторах класса, которые были записаны в нестандартных форматах (подклассами ObjectOutputStream
которые переопределили writeClassDescriptor
метод). По умолчанию этот метод читает дескрипторы класса согласно формату, описанному в Разделе 6.4, "Грамматика для Потокового Формата".
resolveClass
метод вызывают, в то время как класс десериализовывается, и после того, как дескриптор класса был считан. Подклассы могут расширить этот метод, чтобы считать другую информацию о классе, записанном соответствующим подклассом ObjectOutputStream
. Метод должен найти и возвратить класс с именем и serialVersionUID
. Реализация по умолчанию определяет местоположение класса, вызывая загрузчик класса самой близкой вызывающей стороны readObject
у этого есть загрузчик класса. Если класс не может быть найден ClassNotFoundException
должен быть брошен. До JDK 1.1.6, resolveClass
метод был обязан возвращать то же самое полностью определенное имя класса как имя класса в потоке. Чтобы разместить переименование пакета через выпуски, method
resolveClass
только потребности возвратить класс с тем же самым именем базового класса и SerialVersionUID
в JDK 1.1.6 и более поздних версиях.
resolveObject
метод используется доверенными подклассами, чтобы контролировать или заменить одним объектом другого во время десериализации. Разрешение объектов должно быть включено явно, вызывая enableResolveObject
перед вызовом readObject
для первого объекта, который будет разрешен. После того, как включенный, resolveObject
однажды вызывают для каждого сериализуемого объекта только до первого раза, когда это возвращается из readObject
. Отметьте что resolveObject
метод не вызывают для объектов особенно обработанных классов, Class
, ObjectStreamClass
, String
, и массивы. Реализация подкласса resolveObject
может возвратить объект замены, который будет присвоен или возвращен вместо оригинала. Возвращенный объект должен иметь тип, который является непротиворечивым и присваиваемым каждой ссылке исходного объекта или иначе a ClassCastException
будет брошен. Все присвоения проверяются в типе. Все ссылки в потоке к исходному объекту будут заменены ссылками на объект замены.
enableResolveObject
метод вызывают доверяемые подклассы ObjectOutputStream
включать контролю или замене одного объекта для другого во время десериализации. Замена объектов не отключается до enableResolveObject
вызывается с a true
значение. Это может после того быть отключено, устанавливая это в false
. Предыдущая установка возвращается. enableResolveObject
метод проверяет, есть ли у потока разрешение, чтобы запросить замену во время сериализации. Чтобы гарантировать, что частное состояние объектов весьма преднамеренно представляется, только доверяемые потоки могут использовать resolveObject
. Доверяемые классы являются теми классами с загрузчиком класса, равным нулю, или принадлежат домену средства обеспечения безопасности, который обеспечивает разрешение, чтобы включить замене.
Если подкласс ObjectInputStream
не считается частью системного домена, строка должна быть добавлена к файлу политики безопасности, чтобы обеспечить для подкласса ObjectInputStream
разрешение, чтобы вызвать enableResolveObject
. SerializablePermission
добавить "enableSubstitution"
. AccessControlException
бросается если домен защиты подкласса ObjectStreamClass
не имеет разрешения к "enableSubstitution"
вызывая enableResolveObject
. См. Архитектуру безопасности Java документа (JDK 1.2) для дополнительной информации о модели обеспечения безопасности.
readStreamHeader
метод читает и проверяет магическое число и версию потока. Если они не соответствуют, StreamCorruptedMismatch
бросается.
Переопределять реализацию десериализации, подкласс ObjectInputStream
должен вызвать защищенный без аргументов ObjectInputStream
, конструктор. Есть проверка защиты в пределах конструктора без аргументов для SerializablePermission "enableSubclassImplementation"
чтобы гарантировать, который только доверял, классам позволяют переопределить реализацию по умолчанию. Этот конструктор не выделяет частных данных для ObjectInputStream
и устанавливает флаг, который указывает что финал readObject
метод должен вызвать readObjectOverride
метод и возврат. Все другой ObjectInputStream
методы не являются заключительными и могут быть непосредственно переопределены подклассом.
ObjectInputStream.GetField
обеспечивает API для того, чтобы он получил значения сериализуемых полей. Протокол потока является тем же самым как использующийся defaultReadObject.
Используя readFields
получить доступ к сериализуемым полям не изменяет формат потока. Это только обеспечивает альтернативный API, чтобы получить доступ к значениям, который не требует, чтобы у класса были соответствующие непереходные и нестатические поля для каждого именованного сериализуемого поля. Сериализуемые поля - объявленные использованием serialPersistentFields
или если это не объявляется непереходными и нестатическими полями объекта. Когда поток читается, доступные сериализуемые поля - записанные потоку, когда объект был сериализирован. Если класс, который записал поток, будет различной версией не, то все поля будут соответствовать сериализуемым полям текущего класса. Доступные поля могут быть получены от ObjectStreamClass
из GetField
объект.
getObjectStreamClass
метод возвращается ObjectStreamClass
объект, представляющий класс в потоке. Это содержит список сериализуемых полей.
defaulted
метод возвращает true, если поле не присутствует в потоке. IllegalArgumentException
бросается, если требуемое поле не является сериализуемым полем текущего класса.
Каждый get
метод возвращает указанное сериализуемое поле из потока. Исключения ввода-вывода будут выданы, если базовый поток выдаст исключение. IllegalArgumentException
бросается, если имя или тип не соответствуют имя и тип поля сериализуемое поле текущего класса. Значение по умолчанию возвращается, если поток не содержит явное значение для поля.
Этот интерфейс позволяет объекту быть вызванным, когда полный график объектов был десериализован. Если объект не может быть сделан допустимым, он должен бросить ObjectInvalidException
. Любое исключение, которое происходит во время звонка validateObject
завершит процесс проверки допустимости, и InvalidObjectException
будет брошен.
package java.io; public interface ObjectInputValidation { public void validateObject() throws InvalidObjectException; }
readObject
метод позволяет классу управлять десериализацией своих собственных полей. Вот его подпись:private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException;Каждый подкласс сериализуемого объекта может определить свое собственное
readObject
метод. Если класс не реализует метод, сериализация по умолчанию, обеспеченная defaultReadObject
будет использоваться. Когда реализовано, класс только ответственен за восстановление его собственных полей, не таковых из его супертипов или подтипов.
readObject
метод класса, если реализовано, ответственен за восстановление состояния класса. Значения каждого поля объекта или переходного процесса или нет, статичный или не устанавливаются в значение по умолчанию для полевого типа. Также ObjectInputStream
's defaultReadObject
или readFields
метод нужно вызвать однажды (и только однажды) прежде, чем считать любые дополнительные данные, записанные соответствием writeObject
метод; даже если никакие дополнительные данные не читаются, defaultReadObject
или readFields
должен все еще быть вызван однажды. Если readObject
метод класса пытается считать больше данных, чем присутствует в дополнительной части потока для этого класса, поток возвратится -1
для чтений bytewise бросьте EOFException
для примитивных чтений данных (например, readInt
, readFloat
), или бросок OptionalDataException
с eof
полевой набор к true
для объектных чтений.
Ответственность за формат, структуру, и управление версиями дополнительных данных лежит полностью на классе. @serialData
javadoc тегируют в пределах комментария javadoc для readObject
метод должен использоваться, чтобы задокументировать формат и структуру дополнительных данных.
Если восстанавливаемый класс не присутствует в считанном потоке, то readObjectNoData
метод, если определено, вызывается (вместо readObject
); иначе, его поля инициализируются к соответствующим значениям по умолчанию. Для дальнейшей детали см. раздел 3.5.
Чтение объекта от ObjectInputStream
походит на создание нового объекта. Так же, как конструкторы нового объекта вызываются в порядке от суперкласса до подкласса, объект, считанный из потока, десериализовывается от суперкласса до подкласса. readObject
или readObjectNoData
метод вызывают вместо конструктора для каждого Serializable
подкласс во время десериализации.
Одно последнее подобие между конструктором и a readObject
метод - то, что оба обеспечивают возможность вызвать метод на объект, который не полностью создается. Любой переопределяемый (ни частный, статичный, ни заключительный) метод, вызванный, в то время как объект создается, не может потенциально быть переопределен подклассом. Методы, вызванные во время фазы конструкции объекта, разрешаются фактическим типом объекта, не типом, в настоящий момент инициализируемым или его конструктором или readObject
/readObjectNoData
метод. Поэтому, вызывая переопределяемый метод изнутри a readObject
или readObjectNoData
метод может привести к неумышленному вызову метода подкласса прежде, чем суперкласс был полностью инициализирован.
readObjectNoData
метод позволяет классу управлять инициализацией своих собственных полей, когда экземпляр подкласса десериализовывается, и поток сериализации не перечисляет рассматриваемый класс как суперкласс десериализованного объекта. Это может произойти в случаях, где принимающая сторона использует различную версию класса десериализованного экземпляра чем передающая сторона, и версия получателя расширяет классы, которые не расширяются версией отправителя. Это может также произойти, если поток сериализации вмешался; следовательно, readObjectNoData
полезно для инициализации десериализованных объектов должным образом несмотря на "враждебный" или неполный исходный поток.private void readObjectNoData() throws ObjectStreamException;
Каждый сериализуемый класс может определить свое собственное readObjectNoData
метод. Если сериализуемый класс не определяет a readObjectNoData
метод, тогда в сложившейся ситуации упоминал выше поля класса, будет инициализирован к их значениям по умолчанию (как перечислено в Спецификации языка Java); это поведение является непротиворечивым с тем из ObjectInputStream
до версии 1.4 Java 2 SDK, Standard Edition, когда поддержка readObjectNoData
методы были представлены. Если сериализуемый класс действительно определяет a readObjectNoData
метод и вышеупомянутые условия возникают, тогда readObjectNoData
будет вызван в точке во время десериализации когда определенный с помощью класса readObject
метод иначе вызвали бы, имел рассматриваемый класс, перечисленный потоком как суперкласс десериализовываемого экземпляра.
java.io.Externalizable
должен реализовать readExternal
метод, чтобы восстановить все состояние объекта. Это должно скоординировать с его суперклассами, чтобы восстановить их состояние. Все методы ObjectInput
доступны, чтобы восстановить примитивные введенные поля объекта и объектные поля.public void readExternal(ObjectInput stream) throws IOException;
readExternal
метод общедоступен, и он повышает риск клиентской возможности перезаписать существующий объект от потока. Класс может добавить свои собственные проверки, чтобы обеспечить, чтобы это только вызвали когда приспособлено. Externalizable
объекты. Старое определение Externalizable
объекты, требуемые локальная виртуальная машина, чтобы найти a readExternal
метод, чтобы быть в состоянии должным образом читать Externalizable
объект от потока. Новый формат добавляет достаточную информацию к потоковому протоколу, таким образом, сериализация может пропустить Externalizable
возразите когда локальная переменная readExternal
метод не доступен. Из-за правил развития класса, сериализация должна быть в состоянии пропустить Externalizable
объект во входном потоке, если нет отображения для объекта, используя локальные классы.
Дополнительная выгода нового Externalizable
потоковый формат - это ObjectInputStream
может обнаружить попытки считать больше Внешних данных, чем доступно, и может также пропустить любыми данными, которые оставляют неиспользованными a readExternal
метод. Поведение ObjectInputStream
в ответ на чтение мимо конца Внешних данных то же самое как поведение когда определенный с помощью класса readObject
метод пытается читать мимо конца его дополнительных данных: чтения bytewise возвратятся -1
, примитивные чтения бросят EOFException
s, и объектные чтения бросит OptionalDataException
s с eof
полевой набор к true
.
Из-за изменения формата, JDK 1.1.6 и более ранние выпуски не в состоянии считать новый формат. StreamCorruptedException
бросается когда JDK 1.1.6 или более ранние попытки читать Externalizable
объект от потока, записанного в PROTOCOL_VERSION_2
. Проблемы совместимости обсуждаются более подробно в Разделе 6.3, "Потоковые Версии Протокола."
readResolve
метод позволяет классу заменять/решать объект, считанный из потока прежде, чем это будет возвращено к вызывающей стороне. Реализовывая readResolve
метод, класс может непосредственно управлять типами и экземплярами его собственных десериализовываемых экземпляров. Метод определяется следующим образом:ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
readResolve
метод вызывают когда ObjectInputStream
считал объект из потока и готовится возвращать это вызывающей стороне. ObjectInputStream
проверки, определяет ли класс объекта readResolve
метод. Если метод определяется, readResolve
метод вызывают, чтобы позволить объекту в потоке определять объект быть возвращенным. Возвращенный объект должен иметь тип, который является совместимым со всем использованием. Если это не является совместимым, a ClassCastException
будет брошен, когда несоответствие типов обнаруживается.Например, a Symbol
класс мог быть создан, для которого только единственный экземпляр каждой привязки символа существовал в пределах виртуальной машины. readResolve
метод был бы реализован, чтобы определить, был ли тот символ уже определен, и замените эквивалентным существованием ранее Symbol
объект поддержать ограничение идентификационных данных. Таким образом уникальность Symbol
объекты могут сохраняться через сериализацию.
readResolve
метод не вызывается на объект, пока объект полностью не создается, таким образом, любые ссылки на этот объект в его графе объектов не будут обновлены к новому объекту, назначенному readResolve
. Однако, во время сериализации объекта с writeReplace
метод, все ссылки на исходный объект в заменяющем графе объектов объекта заменяются ссылками на заменяющий объект. Поэтому в случаях, где сериализируемый объект назначает заменяющий объект, у графа объектов которого есть ссылка на исходный объект, десериализация приведет к неправильному графику объектов. Кроме того, если ссылочные типы считанного объекта (назначенный writeReplace
) и исходный объект не является совместимым, конструкция графа объектов повысит a ClassCastException
.