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 пишется потоку, дескриптор присваивается для класса, и 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
всегда сериализируется тем же самым способом как недавно появляющийся объект (объект, который еще не был записан потоку), независимо от того, был ли объект записан ранее.writeObject
используется, чтобы записать объект, который был ранее записан с writeUnshared
, предыдущее writeUnshared
работа обрабатывается, как будто это была запись отдельного объекта. Другими словами, ObjectOutputStream
никогда не будет генерировать обратные ссылки, чтобы возразить данным, записанным звонками writeUnshared
.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
методы не являются заключительными и могут быть непосредственно переопределены подклассом.
Класс PutField
обеспечивает API для того, чтобы он установил значения сериализуемых полей для класса, когда класс не использует сериализацию по умолчанию. Каждый метод помещает указанное именованное значение в поток. IllegalArgumentException
бросается если name
не соответствует имя сериализуемого поля для класса, поля которого пишутся, или если тип именованного поля не соответствует второй тип параметра определенного put
метод вызывается.
writeObject
метод позволяет классу управлять сериализацией своих собственных полей. Вот его подпись:
private void writeObject(ObjectOutputStream stream) throws IOException;Каждый подкласс сериализуемого объекта может определить свое собственное
writeObject
метод. Если класс не реализует метод, сериализация по умолчанию, обеспеченная defaultWriteObject
будет использоваться. Когда реализовано, класс только ответственен за запись его собственных полей, не таковых из его супертипов или подтипов. Класс writeObject
метод, если реализовано, ответственен за сохранение состояния класса. Также ObjectOutputStream
's defaultWriteObject
или writeFields
метод нужно вызвать однажды (и только однажды) прежде, чем записать любые дополнительные данные, которые будут необходимы соответствию readObject
метод, чтобы восстановить состояние объекта; даже если никакие дополнительные данные не пишутся, defaultWriteObject
или writeFields
должен все еще быть вызван однажды. Если defaultWriteObject
или writeFields
не вызывается однажды до записи дополнительных данных (если любой), то поведение десериализации экземпляра неопределено в случаях где ObjectInputStream
не может разрешить класс, который определил writeObject
рассматриваемый метод.
Ответственность за формат, структуру, и управление версиями дополнительных данных лежит полностью на классе.
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
метод позволяет классу объекта назначить его собственную замену в потоке прежде, чем объект будет записан. Реализовывая writeReplace
метод, класс может непосредственно управлять типами и экземплярами его собственных сериализируемых экземпляров. Метод определяется следующим образом:
ANY-ACCESS-MODIFIER Object writeReplace() { throws ObjectStreamException;
writeReplace
метод вызывают когда ObjectOutputStream
готовится писать объект в поток. ObjectOutputStream
проверки, определяет ли класс writeReplace
метод. Если метод определяется, writeReplace
метод вызывают, чтобы позволить объекту определять его замену в потоке. Возвращенный объект должен быть или того же самого типа как объект, который передают в или объекта, который когда считано и разрешено приведет к объекту типа, который является совместимым со всеми ссылками на объект. Если это не, a ClassCastException
произойдет, когда несоответствие типов обнаруживается.
Потоковые версии протокола обсуждаются в Разделе 6.3, "Потоковые Версии Протокола."