Spec-Zone .ru
спецификации, руководства, описания, API
СОДЕРЖАНИЕ | ПРЕДЫДУЩИЙ | NEXT Спецификация Сериализации Объекта Java
версия 6.0

Объектные Входные Классы






ГЛАВА 3

Темы:


3.1 Класс ObjectInputStream

Класс 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 лишает законной силы потоковый дескриптор, связанный с возвращенным объектом. Отметьте, что это сам по себе не всегда гарантирует что ссылка, возвращенная 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 методы не являются заключительными и могут быть непосредственно переопределены подклассом.


3.2 ObjectInputStream. Класс GetField

Класс ObjectInputStream.GetField обеспечивает API для того, чтобы он получил значения сериализуемых полей. Протокол потока является тем же самым как использующийся defaultReadObject. Используя readFields получить доступ к сериализуемым полям не изменяет формат потока. Это только обеспечивает альтернативный API, чтобы получить доступ к значениям, который не требует, чтобы у класса были соответствующие непереходные и нестатические поля для каждого именованного сериализуемого поля. Сериализуемые поля - объявленные использованием serialPersistentFields или если это не объявляется непереходными и нестатическими полями объекта. Когда поток читается, доступные сериализуемые поля - записанные потоку, когда объект был сериализирован. Если класс, который записал поток, будет различной версией не, то все поля будут соответствовать сериализуемым полям текущего класса. Доступные поля могут быть получены от ObjectStreamClass из GetField объект.

getObjectStreamClass метод возвращается ObjectStreamClass объект, представляющий класс в потоке. Это содержит список сериализуемых полей.

defaulted метод возвращает true, если поле не присутствует в потоке. IllegalArgumentException бросается, если требуемое поле не является сериализуемым полем текущего класса.

Каждый get метод возвращает указанное сериализуемое поле из потока. Исключения ввода-вывода будут выданы, если базовый поток выдаст исключение. IllegalArgumentException бросается, если имя или тип не соответствуют имя и тип поля сериализуемое поле текущего класса. Значение по умолчанию возвращается, если поток не содержит явное значение для поля.


3.3 Интерфейс ObjectInputValidation

Этот интерфейс позволяет объекту быть вызванным, когда полный график объектов был десериализован. Если объект не может быть сделан допустимым, он должен бросить ObjectInvalidException. Любое исключение, которое происходит во время звонка validateObject завершит процесс проверки допустимости, и InvalidObjectException будет брошен.

package java.io;

public interface ObjectInputValidation
{
    public void validateObject()
        throws InvalidObjectException;
}

3.4 readObject Метод

Для сериализуемых объектов, 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 метод может привести к неумышленному вызову метода подкласса прежде, чем суперкласс был полностью инициализирован.


3.5 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 метод иначе вызвали бы, имел рассматриваемый класс, перечисленный потоком как суперкласс десериализовываемого экземпляра.


3.6 readExternal Метод

Реализация объектов java.io.Externalizable должен реализовать readExternal метод, чтобы восстановить все состояние объекта. Это должно скоординировать с его суперклассами, чтобы восстановить их состояние. Все методы ObjectInput доступны, чтобы восстановить примитивные введенные поля объекта и объектные поля.

    public void readExternal(ObjectInput stream)
        throws IOException;

Отметьте - readExternal метод общедоступен, и он повышает риск клиентской возможности перезаписать существующий объект от потока. Класс может добавить свои собственные проверки, чтобы обеспечить, чтобы это только вызвали когда приспособлено.
Новая потоковая версия протокола была представлена в JDK 1.2, чтобы исправить проблему с Externalizable объекты. Старое определение Externalizable объекты, требуемые локальная виртуальная машина, чтобы найти a readExternal метод, чтобы быть в состоянии должным образом читать Externalizable объект от потока. Новый формат добавляет достаточную информацию к потоковому протоколу, таким образом, сериализация может пропустить Externalizable возразите когда локальная переменная readExternal метод не доступен. Из-за правил развития класса, сериализация должна быть в состоянии пропустить Externalizable объект во входном потоке, если нет отображения для объекта, используя локальные классы.

Дополнительная выгода нового Externalizable потоковый формат - это ObjectInputStream может обнаружить попытки считать больше Внешних данных, чем доступно, и может также пропустить любыми данными, которые оставляют неиспользованными a readExternal метод. Поведение ObjectInputStream в ответ на чтение мимо конца Внешних данных то же самое как поведение когда определенный с помощью класса readObject метод пытается читать мимо конца его дополнительных данных: чтения bytewise возвратятся -1, примитивные чтения бросят EOFExceptions, и объектные чтения бросит OptionalDataExceptions с eof полевой набор к true.

Из-за изменения формата, JDK 1.1.6 и более ранние выпуски не в состоянии считать новый формат. StreamCorruptedException бросается когда JDK 1.1.6 или более ранние попытки читать Externalizable объект от потока, записанного в PROTOCOL_VERSION_2. Проблемы совместимости обсуждаются более подробно в Разделе 6.3, "Потоковые Версии Протокола."


3.7 readResolve Метод

Для классов Serializable и Externalizable, 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.


СОДЕРЖАНИЕ | ПРЕДЫДУЩИЙ | NEXT
Авторское право © 2005, 2010, Oracle и/или его филиалы. Все права защищены.