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

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






ГЛАВА 2

Темы:


2.1 Класс ObjectOutputStream

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

package java.io;

public class ObjectOutputStream
    extends OutputStream
    implements ObjectOutput, ObjectStreamConstants
{
    public ObjectOutputStream(OutputStream out)
        throws IOException;

    public final void writeObject(Object obj)
        throws IOException;

    public void writeUnshared(Object obj)
        throws IOException;

    public void defaultWriteObject()
        throws IOException, NotActiveException;

    public PutField putFields()
        throws IOException;

    public writeFields()
        throws IOException;

    public void reset() throws IOException;

    protected void annotateClass(Class cl) throws IOException;

    protected void writeClassDescriptor(ObjectStreamClass desc)
        throws IOException;

    protected Object replaceObject(Object obj) throws IOException;

    protected boolean enableReplaceObject(boolean enable)
        throws SecurityException;

    protected void writeStreamHeader() throws IOException;

    public void write(int data) throws IOException;

    public void write(byte b[]) throws IOException;

    public void write(byte b[], int off, int len) throws IOException;

    public void flush() throws IOException;

    protected void drain() throws IOException;

    public void close() throws IOException;

    public void writeBoolean(boolean data) throws IOException;

    public void writeByte(int data) throws IOException;

    public void writeShort(int data) throws IOException;

    public void writeChar(int data) throws IOException;

    public void writeInt(int data) throws IOException;

    public void writeLong(long data) throws IOException;

    public void writeFloat(float data) throws IOException;

    public void writeDouble(double data) throws IOException;

    public void writeBytes(String data) throws IOException;

    public void writeChars(String data) throws IOException;

    public void writeUTF(String data) throws IOException;

    // Inner class to provide access to serializable fields.
    abstract static public class PutField
    {
        public void put(String name, boolean value)
            throws IOException, IllegalArgumentException;

        public void put(String name, char data)
            throws IOException, IllegalArgumentException;

        public void put(String name, byte data)
            throws IOException, IllegalArgumentException;

        public void put(String name, short data)
            throws IOException, IllegalArgumentException;

        public void put(String name, int data)
            throws IOException, IllegalArgumentException;

        public void put(String name, long data)
            throws IOException, IllegalArgumentException;

        public void put(String name, float data)
            throws IOException, IllegalArgumentException;

        public void put(String name, double data)
            throws IOException, IllegalArgumentException;

        public void put(String name, Object data)
            throws IOException, IllegalArgumentException;
    }

    public void useProtocolVersion(int version) throws IOException;

    protected ObjectOutputStream()
        throws IOException;

     protected writeObjectOverride()
        throws NotActiveException, IOException;
}
Единственный параметр ObjectOutputStream конструктор создает ObjectOutputStream это сериализирует объекты к данному OutputStream. Вызовы конструктора writeStreamHeader записать магическое число и версию к потоку, который будет считан и проверен соответствующим звонком readStreamHeader в единственном параметре ObjectInputStream конструктор. Если менеджер безопасности устанавливается, этот конструктор проверки на "enableSubclassImplementation" SerializablePermission когда вызвано прямо или косвенно конструктором подкласса, который переопределяет putFields и/или writeUnshared методы.

writeObject метод используется, чтобы сериализировать объект к потоку. Объект сериализируется следующим образом:

  1. Если подкласс переопределяет реализацию, вызовите writeObjectOverride метод и возврат. Переопределение реализации описывается в конце этого раздела.
  2. Если есть данные в блочном буфере данных, данные пишутся потоку, и буфер сбрасывается.
  3. Если объект является нулем, нуль помещается в поток и writeObject возвраты.
  4. Если объект был ранее заменен, как описано в Шаге 8, запишите дескриптор замены к потоку и writeObject возвраты.
  5. Если объект был уже записан потоку, его дескриптор пишется потоку и writeObject возвраты.
  6. Если объект является a Class, соответствие ObjectStreamClass пишется потоку, дескриптор присваивается для класса, и writeObject возвраты.
  7. Если объект ObjectStreamClass, дескриптор присваивается объекту, после которого он пишется потоку, используя один из форматов дескриптора класса, описанных в разделе 4.3. В версиях 1.3 и позже Java 2 SDK, Standard Edition, writeClassDescriptor метод вызывают, чтобы вывести ObjectStreamClass если это представляет класс, который не является динамическим прокси-классом, как определено, передавая связанное Class возразите против isProxyClass метод java.lang.reflect.Proxy. Впоследствии, аннотация для представленного класса пишется: если класс является динамическим прокси-классом, то annotateProxyClass метод вызывают; иначе, annotateClass метод вызывают. writeObject метод тогда возвращается.
  8. Обработайте потенциальные замены классом объекта и/или подклассом ObjectInputStream.
  a. Если класс объекта не является перечислимым типом и определяет соответствующее writeReplace метод, метод вызывают. Дополнительно, это может возвратить объект замены, который будет сериализирован.
  b. Затем, если включено, вызывая enableReplaceObject метод, replaceObject метод вызывают, чтобы позволить подклассы ObjectOutputStream заменять сериализируемый объект. Если исходный объект был заменен в предыдущем шаге, replaceObject метод вызывают с заменяющим объектом.
  Если исходный объект был заменен или одним или обоими шагами выше, отображение от исходного объекта до замены записывается для более позднего использования в Шаге 4. Затем, Шаги 3 - 7 повторяются на новом объекте.
  Если заменяющий объект не является одним из типов, покрытых Шагами 3 - 7, обрабатывая резюме, используя заменяющий объект в Шаге 10.
  9. Если объект является a java.lang.String, строка пишется как информация о длине, сопровождаемая содержанием строки, закодированной в измененном UTF-8. Для получения дополнительной информации отнеситесь, чтобы Разделить 6.2, "Потоковые Элементы". Дескриптор присваивается строке, и writeObject возвраты.
  10. Если объект является массивом, writeObject вызывается рекурсивно, чтобы записать ObjectStreamClass из массива. Дескриптор для массива присваивается. Это сопровождается длиной массива. Каждый элемент массива тогда пишется потоку, после который writeObject возвраты.
  11. Если объект является перечислимой константой, ObjectStreamClass поскольку перечислимый тип константы пишется, рекурсивно вызывая writeObject. Это появится в потоке только в первый раз, когда на это ссылаются. Дескриптор присваивается для перечислимой константы. Затем, значение, возвращенное name метод перечислимой константы пишется как a String объект, как описано в шаге 9. Отметьте, что, если та же самая строка имени появилась ранее в потоке, обратная ссылка на это будет записана. writeObject метод тогда возвращается.
  12. Для регулярных объектов, ObjectStreamClass поскольку класс объекта пишется, рекурсивно вызывая writeObject. Это появится в потоке только в первый раз, когда на это ссылаются. Дескриптор присваивается для объекта.
  13. Содержание объекта пишется потоку.
  a. Если объект сериализуем, самый высокий сериализуемый класс располагается. Для того класса, и каждого производного класса, что поля класса пишутся. Если у класса нет a writeObject метод, defaultWriteObject метод вызывают, чтобы записать сериализуемые поля в поток. Если у класса действительно есть a writeObject метод, это вызывают. Это может вызвать defaultWriteObject или putFields и writeFields чтобы сохранить состояние объекта, и затем это может записать другую информацию в поток.
  b. Если объект является externalizable, writeExternal метод объекта вызывают.
  c. Если объект ни один не сериализуем или externalizable, NotSerializableException бросается.

Исключения могут произойти во время обхода или могут произойти в базовом потоке. Для любого подкласса IOException, исключение пишется потоку, используя протокол исключения, и потоковое состояние отбрасывается. Если секунда IOException бросается, пытаясь записать первое исключение в поток, поток покидают в неизвестном состоянии и StreamCorruptedException бросается от writeObject. Для других исключений поток прерывается и покидается в неизвестном и неприменимом состоянии.

writeUnshared метод пишет "неразделенный" объект в ObjectOutputStream. Этот метод идентичен writeObject, за исключением того, что это всегда пишет данный объект как новый, уникальный объект в потоке (в противоположность обратной ссылке, указывающей на ранее сериализированный экземпляр). Определенно:
При записи объекта через writeUnshared сам по себе не гарантирует уникальную ссылку на объект, когда он десериализовывается, он позволяет единственному объекту быть определенным многократно в потоке, так, чтобы множественные вызовы ObjectInputStream.readUnshared метод (см. Раздел 3.1, "Класс ObjectInputStream") получателем не будет конфликтовать. Отметьте, что правила, описанные выше только, применяются к объекту на основном уровне, записанному с writeUnshared, а не к любому transitively подобъекты, на которые ссылаются, в графе объектов, который будет сериализирован.

defaultWriteObject метод реализует механизм сериализации по умолчанию для текущего класса. Этот метод можно вызвать только от класса writeObject метод. Метод пишет все сериализуемые поля текущего класса потока. Если вызвано снаружи writeObject метод, NotActiveException бросается.

putFields метод возвращает a PutField возразите использованию вызывающей стороны, чтобы установить значения сериализуемых полей в потоке. Поля могут быть установлены в любом порядке. После того, как все поля были установлены, writeFields должен быть вызван, чтобы записать значения полей в каноническом порядке к потоку. Если поле не будет установлено, то значение по умолчанию, подходящее для его типа, будет записано потоку. Этот метод можно только вызвать изнутри writeObject метод сериализуемого класса. Это нельзя вызвать не раз или если defaultWriteObject был вызван. Только после writeFields был вызван может другие данные быть записанным потоку.

reset метод сбрасывает потоковое состояние, чтобы быть тем же самым, как будто это было только что создано. Reset отбросит состояние любых объектов, уже записанных потоку. Текущая точка в потоке отмечается как сброшено, таким образом, соответствие ObjectInputStream сбросит в той же самой точке. Объекты, ранее записанные потоку, не будут помнить как уже записанный потоку. Они будут записаны потоку снова. Это полезно, когда содержание объекта или объектов должно быть отправлено снова. Reset возможно, не вызывается, в то время как объекты сериализируются. Если вызвано неуместно, IOException бросается.

Запускаясь с Java 2 SDK, Standard Edition, v1.3, writeClassDescriptor метод вызывают когда ObjectStreamClass потребности, которые будут сериализированы. writeClassDescriptor ответственно за запись представления ObjectStreamClass к потоку сериализации. Подклассы могут переопределить этот метод, чтобы настроить путь, которым дескрипторы класса пишутся потоку сериализации. Если этот метод переопределяется, то соответствие readClassDescriptor метод в ObjectInputStream должен также быть переопределен, чтобы воссоздать дескриптор класса от его пользовательского потокового представления. По умолчанию, writeClassDescriptor дескрипторы класса записей согласно формату, определенному в Разделе 6.4, "Грамматика для Потокового Формата". Отметьте, что этот метод только вызовут если ObjectOutputStream не использует старый потоковый формат сериализации (см. Раздел 6.3, "Потоковые Версии Протокола"). Если поток сериализации использует старый формат (ObjectStreamConstants.PROTOCOL_VERSION_1), дескриптор класса будет записан внутренне способом, который не может быть переопределен или настроен.

annotateClass метод вызывают в то время как a Class сериализируется, и после того, как дескриптор класса был записан потоку. Подклассы могут расширить этот метод и записать другую информацию в поток о классе. Эта информация должна быть считана resolveClass метод в соответствии ObjectInputStream подкласс.

ObjectOutputStream подкласс может реализовать replaceObject метод, чтобы контролировать или заменить объекты во время сериализации. Замена объектов должна быть включена явно, вызывая enableReplaceObject перед вызовом writeObject с первым объектом, который будет заменен. После того, как включенный, replaceObject вызывается для каждого объекта только до сериализации объекта впервые. Отметьте что replaceObject метод не вызывают для объектов особенно обработанных классов, Class и ObjectStreamClass. Реализация подкласса может возвратить объект замены, который будет сериализирован вместо оригинала. Объект замены должен быть сериализуемым. Все ссылки в потоке к исходному объекту будут заменены объектом замены.

Когда объекты заменяются, подкласс должен гарантировать, что объект, которым заменяют, является совместимым с каждым полем, где ссылка будет сохранена, или что дополнительная замена будет сделана во время десериализации. Объекты, тип которых не является подклассом типа поля или элемента массива, позже прервут десериализацию, повышая a ClassCastException и ссылка не будет сохранена.

enableReplaceObject метод могут вызвать доверяемые подклассы ObjectOutputStream включать замене одного объекта для другого во время сериализации. Замена объектов не отключается до enableReplaceObject вызывается с a true значение. Это может после того быть отключено, устанавливая это в false. Предыдущая установка возвращается. enableReplaceObject метод проверяет, что потоку, запрашивающему замену, можно доверять. Чтобы гарантировать, что частное состояние объектов весьма преднамеренно представляется, только доверяемые потоковые подклассы могут использовать replaceObject. Доверяемые классы являются теми классами, которые принадлежат домену средства обеспечения безопасности с разрешением, чтобы включить Сериализуемой замене.

Если подкласс ObjectOutputStream не считается частью системного домена, SerializablePermission "enableSubstitution" должен быть добавлен к файлу политики безопасности. AccessControlException бросается если домен защиты подкласса ObjectInputStream не имеет разрешения к "enableSubstitution" вызывая enableReplaceObject. См. Архитектуру безопасности Java документа (JDK1.2) для дополнительной информации о модели обеспечения безопасности.

writeStreamHeader метод пишет магическое число и версию к потоку. Эта информация должна быть считана readStreamHeader метод ObjectInputStream. Подклассы, возможно, должны реализовать этот метод, чтобы идентифицировать уникальный формат потока.

flush метод используется, чтобы освободить любые буферы, сохраненные потоком и передать сброс базовому потоку. drain метод может использоваться подклассификаторами, чтобы опустеть только ObjectOutputStream's буферизует, не вынуждая базовый поток быть сброшенным.

Все методы записи для типов примитивов кодируют их значения, используя a DataOutputStream помещать их в стандартный потоковый формат. Байты буферизуются в блочные записи данных, таким образом, их можно отличить от кодирования объектов. Эта буферизация позволяет примитивным данным быть пропущенными в случае необходимости для управления версиями класса. Это также позволяет потоку быть проанализированным, не вызывая специфичные для класса методы.

Переопределять реализацию сериализации, подкласс ObjectOutputStream должен вызвать защищенный без аргументов ObjectOutputStream, конструктор. Есть проверка защиты в пределах конструктора без аргументов для SerializablePermission "enableSubclassImplementation" чтобы гарантировать, который только доверял, классам позволяют переопределить реализацию по умолчанию. Этот конструктор не выделяет частных данных для ObjectOutputStream и устанавливает флаг, который указывает что финал writeObject метод должен вызвать writeObjectOverride метод и возврат. Все другой ObjectOutputStream методы не являются заключительными и могут быть непосредственно переопределены подклассом.


2.2 ObjectOutputStream. Класс PutField

Класс PutField обеспечивает API для того, чтобы он установил значения сериализуемых полей для класса, когда класс не использует сериализацию по умолчанию. Каждый метод помещает указанное именованное значение в поток. IllegalArgumentException бросается если name не соответствует имя сериализуемого поля для класса, поля которого пишутся, или если тип именованного поля не соответствует второй тип параметра определенного put метод вызывается.


2.3 writeObject Метод

Для сериализуемых объектов, writeObject метод позволяет классу управлять сериализацией своих собственных полей. Вот его подпись:

    private void writeObject(ObjectOutputStream stream)
        throws IOException;
Каждый подкласс сериализуемого объекта может определить свое собственное writeObject метод. Если класс не реализует метод, сериализация по умолчанию, обеспеченная defaultWriteObject будет использоваться. Когда реализовано, класс только ответственен за запись его собственных полей, не таковых из его супертипов или подтипов.

Класс writeObject метод, если реализовано, ответственен за сохранение состояния класса. Также ObjectOutputStream's defaultWriteObject или writeFields метод нужно вызвать однажды (и только однажды) прежде, чем записать любые дополнительные данные, которые будут необходимы соответствию readObject метод, чтобы восстановить состояние объекта; даже если никакие дополнительные данные не пишутся, defaultWriteObject или writeFields должен все еще быть вызван однажды. Если defaultWriteObject или writeFields не вызывается однажды до записи дополнительных данных (если любой), то поведение десериализации экземпляра неопределено в случаях где ObjectInputStream не может разрешить класс, который определил writeObject рассматриваемый метод.

Ответственность за формат, структуру, и управление версиями дополнительных данных лежит полностью на классе.


2.4 writeExternal Метод

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

    public void writeExternal(ObjectOutput stream)
        throws IOException;

Новый формат по умолчанию для того, чтобы записать данные Externalizable был представлен в JDK 1.2. Новый формат определяет, что примитивные данные будут записаны в блочном режиме данных writeExternal методы. Дополнительно, тег, обозначающий конец Внешнего объекта, добавляется к потоку после writeExternal возвраты метода. Преимущества этого изменения формата обсуждаются в Разделе 3.6, "readExternal Метод." Проблемы совместимости, вызванные этим изменением, обсуждаются в Разделе 2.6, "useProtocolVersion Метод."


2.5 writeReplace Метод

Для классов Serializable и Externalizable, writeReplace метод позволяет классу объекта назначить его собственную замену в потоке прежде, чем объект будет записан. Реализовывая writeReplace метод, класс может непосредственно управлять типами и экземплярами его собственных сериализируемых экземпляров.

Метод определяется следующим образом:

   ANY-ACCESS-MODIFIER Object writeReplace() {
                 throws ObjectStreamException;

writeReplace метод вызывают когда ObjectOutputStream готовится писать объект в поток. ObjectOutputStream проверки, определяет ли класс writeReplace метод. Если метод определяется, writeReplace метод вызывают, чтобы позволить объекту определять его замену в потоке. Возвращенный объект должен быть или того же самого типа как объект, который передают в или объекта, который когда считано и разрешено приведет к объекту типа, который является совместимым со всеми ссылками на объект. Если это не, a ClassCastException произойдет, когда несоответствие типов обнаруживается.


2.6 useProtocolVersion Метод

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

Потоковые версии протокола обсуждаются в Разделе 6.3, "Потоковые Версии Протокола."



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