Spec-Zone .ru
спецификации, руководства, описания, API
|
СОДЕРЖАНИЕ | ПРЕДЫДУЩИЙ | NEXT | Спецификация Сериализации Объекта Java версия 6.0 |
ГЛАВА 2 |
Темы:
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 пишется потоку, дескриптор присваивается для class, и writeObject возвраты. |
7. | Если объект ObjectStreamClass , дескриптор присваивается объекту, после которого он пишется потоку, используя один из форматов дескриптора class, описанных в разделе 4.3. В версиях 1.3 и позже Java 2 SDK, Standard Edition, writeClassDescriptor метод вызывают, чтобы вывести ObjectStreamClass если это представляет class, который не является динамическим прокси class, как определено, передавая связанное Class возразите против isProxyClass метод java.lang.reflect.Proxy . Впоследствии, аннотация для представленного class пишется: если class является динамическим прокси class, то annotateProxyClass метод вызывают; иначе, annotateClass метод вызывают. writeObject метод тогда возвращается. |
8. | Обработайте потенциальные замены class объекта и/или подклассом ObjectInputStream . |
a. | Если class объекта не является перечислимым типом и определяет соответствующее 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 поскольку class объекта пишется, рекурсивно вызывая writeObject . Это появится в потоке только в первый раз, когда на это ссылаются. Дескриптор присваивается для объекта. |
13. | Содержание объекта пишется потоку. |
a. | Если объект сериализуем, самый высокий сериализуемый class располагается. Для того, что class, и каждый получил class, что поля class пишутся. Если у class нет a writeObject метод, defaultWriteObject метод вызывают, чтобы записать сериализуемые поля в поток. Если у class действительно есть a writeObject метод, это вызывают. Это может вызвать defaultWriteObject или putFields и writeFields чтобы сохранить состояние объекта, и затем это может записать другую информацию в поток. |
b. | Если объект является externalizable, writeExternal метод объекта вызывают. |
c. | Если объект ни один не сериализуем или externalizable, NotSerializableException бросается. |
Исключения могут произойти во время обхода или могут произойти в базовом потоке. Для любого подкласса IOException
, исключение пишется потоку, используя протокол исключения, и потоковое состояние отбрасывается. Если секунда IOException
бросается, пытаясь записать первое исключение в поток, поток покидают в неизвестном состоянии и StreamCorruptedException
бросается от writeObject
. Для других исключений поток прерывается и покидается в неизвестном и неприменимом состоянии.
writeUnshared
метод пишет "неразделенный" объект в ObjectOutputStream
. Этот метод идентичен writeObject
, за исключением того, что это всегда пишет данный объект как новый, уникальный объект в потоке (в противоположность обратной ссылке, указывающей на ранее сериализированный экземпляр). Определенно: writeUnshared
всегда сериализируется тем же самым способом как недавно появляющийся объект (объект, который еще не был записан потоку), независимо от того, был ли объект записан ранее.writeObject
используется, чтобы записать объект, который был ранее записан с writeUnshared
, предыдущее writeUnshared
работа обрабатывается, как будто это была запись отдельного объекта. Другими словами, ObjectOutputStream
никогда не будет генерировать обратные ссылки, чтобы возразить данным, записанным звонками writeUnshared
.writeUnshared
сам по себе не гарантирует уникальную ссылку на объект, когда он десериализовывается, он позволяет единственному объекту быть определенным многократно в потоке, так, чтобы множественные вызовы ObjectInputStream.readUnshared
метод (см. Раздел 3.1, "Класс ObjectInputStream") получателем не будет конфликтовать. Отметьте, что правила, описанные выше только, применяются к объекту на основном уровне, записанному с writeUnshared
, а не к любому transitively подобъекты, на которые ссылаются, в графе объектов, который будет сериализирован. defaultWriteObject
метод реализует механизм сериализации значения по умолчанию для текущего class. Этот метод можно вызвать только от class writeObject
метод. Метод пишет все сериализуемые поля текущего class к потоку. Если вызвано снаружи writeObject
метод, NotActiveException
бросается.
putFields
метод возвращает a PutField
возразите использованию вызывающей стороны, чтобы установить значения сериализуемых полей в потоке. Поля могут быть установлены в любом порядке. После того, как все поля были установлены, writeFields
должен быть вызван, чтобы записать значения полей в каноническом порядке к потоку. Если поле не будет установлено, то значение по умолчанию, подходящее для его типа, будет записано потоку. Этот метод можно только вызвать изнутри writeObject
метод сериализуемого class. Это нельзя вызвать не раз или если defaultWriteObject
был вызван. Только после writeFields
был вызван может другие данные быть записанным потоку.
reset
метод сбрасывает потоковое состояние, чтобы быть тем же самым, как будто это было только что создано. Reset
отбросит состояние любых объектов, уже записанных потоку. Текущая точка в потоке отмечается как сброшено, таким образом, соответствие ObjectInputStream
сбросит в той же самой точке. Объекты, ранее записанные потоку, не будут помнить как уже записанный потоку. Они будут записаны потоку снова. Это полезно, когда содержание объекта или объектов должно быть отправлено снова. Reset
возможно, не вызывается, в то время как объекты сериализируются. Если вызвано неуместно, IOException
бросается.
Запускаясь с Java 2 SDK, Standard Edition, v1.3, writeClassDescriptor
метод вызывают когда ObjectStreamClass
потребности, которые будут сериализированы. writeClassDescriptor
ответственно за запись представления ObjectStreamClass
к потоку сериализации. Подклассы могут переопределить этот метод, чтобы настроить путь, которым дескрипторы class пишутся потоку сериализации. Если этот метод переопределяется, то соответствие readClassDescriptor
метод в ObjectInputStream
должен также быть переопределен, чтобы воссоздать дескриптор class от его пользовательского потокового представления. По умолчанию, writeClassDescriptor
записи дескрипторы class согласно формату, определенному в Разделе 6.4, "Грамматика для Потокового Формата". Отметьте, что этот метод только вызовут если ObjectOutputStream
не использует старый потоковый формат сериализации (см. Раздел 6.3, "Потоковые Версии Протокола"). Если поток сериализации использует старый формат (ObjectStreamConstants.PROTOCOL_VERSION_1
), дескриптор class будет записан внутренне способом, который не может быть переопределен или настроен.
annotateClass
метод вызывают в то время как a Class
сериализируется, и после того, как дескриптор class был записан потоку. Подклассы могут расширить этот метод и записать другую информацию в поток о 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
помещать их в стандартный потоковый формат. Байты буферизуются в блочные записи данных, таким образом, их можно отличить от кодирования объектов. Эта буферизация позволяет примитивным данным быть пропущенными в случае необходимости для управления версиями class. Это также позволяет потоку быть проанализированным, не вызывая class специфичные методы.
Переопределять реализацию сериализации, подкласс ObjectOutputStream
должен вызвать защищенный без аргументов ObjectOutputStream
, конструктор. Есть проверка защиты в пределах конструктора без аргументов для SerializablePermission "enableSubclassImplementation"
чтобы гарантировать, который только доверял, классам позволяют переопределить реализацию по умолчанию. Этот конструктор не выделяет частных данных для ObjectOutputStream
и устанавливает флаг, который указывает что финал writeObject
метод должен вызвать writeObjectOverride
метод и возврат. Все другой ObjectOutputStream
методы не являются заключительными и могут быть непосредственно переопределены подклассом.
Класс PutField
обеспечивает API для того, чтобы он установил значения сериализуемых полей для class, когда class не использует сериализацию значения по умолчанию. Каждый метод помещает указанное именованное значение в поток. IllegalArgumentException
бросается если name
не соответствует имя сериализуемого поля для class, поля которого пишутся, или если тип именованного поля не соответствует второй тип параметра определенного put
метод вызывается.
writeObject
метод позволяет class управлять сериализацией своих собственных полей. Вот его подпись:
private void writeObject(ObjectOutputStream stream) throws IOException;Каждый подкласс сериализуемого объекта может определить свое собственное
writeObject
метод. Если class не реализует метод, сериализация значения по умолчанию, обеспеченная defaultWriteObject
будет использоваться. Когда реализовано, class только ответственен за запись его собственных полей, не таковых из его супертипов или подтипов. class writeObject
метод, если реализовано, ответственен за сохранение состояния class. Также ObjectOutputStream
's defaultWriteObject
или writeFields
метод нужно вызвать однажды (и только однажды) прежде, чем записать любые дополнительные данные, которые будут необходимы соответствию readObject
метод, чтобы восстановить состояние объекта; даже если никакие дополнительные данные не пишутся, defaultWriteObject
или writeFields
должен все еще быть вызван однажды. Если defaultWriteObject
или writeFields
не вызывается однажды до записи дополнительных данных (если любой), то поведение десериализации экземпляра неопределено в случаях где ObjectInputStream
не может разрешить class, который определил writeObject
рассматриваемый метод.
Ответственность за формат, структуру, и управление версиями дополнительных данных лежит полностью на class.
java.io.Externalizable
должен реализовать writeExternal
метод, чтобы сохранить все состояние объекта. Это должно скоординировать с его суперклассами, чтобы сохранить их состояние. Все методы ObjectOutput
доступны, чтобы сохранить примитивные введенные поля объекта и объектные поля.
public void writeExternal(ObjectOutput stream) throws IOException;
Новый формат значения по умолчанию для того, чтобы записать данные Externalizable был представлен в JDK 1.2. Новый формат определяет, что примитивные данные будут записаны в блочном режиме данных writeExternal
методы. Дополнительно, тег, обозначающий конец Внешнего объекта, добавляется к потоку после writeExternal
возвраты метода. Преимущества этого изменения формата обсуждаются в Разделе 3.6, "readExternal Метод." Проблемы совместимости, вызванные этим изменением, обсуждаются в Разделе 2.6, "useProtocolVersion Метод."
writeReplace
метод позволяет class объекта назначить его собственную замену в потоке прежде, чем объект будет записан. Реализовывая writeReplace
метод, class может непосредственно управлять типами и экземплярами его собственных сериализируемых экземпляров. Метод определяется следующим образом:
ANY-ACCESS-MODIFIER Object writeReplace() { throws ObjectStreamException;
writeReplace
метод вызывают когда ObjectOutputStream
готовится писать объект в поток. ObjectOutputStream
проверки, определяет ли class writeReplace
метод. Если метод определяется, writeReplace
метод вызывают, чтобы позволить объекту определять его замену в потоке. Возвращенный объект должен быть или того же самого типа как объект, который передают в или объекта, который когда считано и разрешено приведет к объекту типа, который является совместимым со всеми ссылками на объект. Если это не, a ClassCastException
произойдет, когда несоответствие типов обнаруживается.
Потоковые версии протокола обсуждаются в Разделе 6.3, "Потоковые Версии Протокола."