Spec-Zone .ru
спецификации, руководства, описания, API
|
СОДЕРЖАНИЕ | ПРЕДЫДУЩИЙ | NEXT | Спецификация Сериализации Объекта Java версия 6.0 |
ГЛАВА 1
Serializable
или Externalizable
интерфейс. Для объектов JavaTM сериализированная форма должна быть в состоянии идентифицировать и проверить класс JavaTM, от которого содержание объекта было сохранено и восстановить содержание к новому экземпляру. Для сериализуемых объектов поток включает достаточную информацию, чтобы восстановить поля в потоке к совместимой версии класса. Для объектов Экстернэлизэйбла класс исключительно ответственен за внешний формат его содержания. Объекты, которые будут сохранены и получены часто, обращаются к другим объектам. Те другие объекты должны храниться и получены одновременно, чтобы поддерживать отношения между объектами. Когда объект хранится, все объекты, которые достижимы от того объекта, хранятся также.
Цели для того, чтобы сериализировать объекты JavaTM к:
// Serialize today's date to a file. FileOutputStream f = new FileOutputStream("tmp"); ObjectOutput s = new ObjectOutputStream(f); s.writeObject("Today"); s.writeObject(new Date()); s.flush();Сначала
OutputStream
, в этом случае a FileOutputStream
, необходим, чтобы получить байты. Затем ObjectOutputStream
создается что записи к FileOutputStream
. Затем, строка "Сегодня" и объект Даты пишутся потоку. Более широко объекты пишутся с writeObject
метод и примитивы пишутся потоку с методами DataOutput
. writeObject
метод (см. Раздел 2.3, "writeObject Метод") сериализирует указанный объект и пересекает его ссылки на другие объекты в графе объектов рекурсивно, чтобы создать полное сериализированное представление графика. В потоке первая ссылка на любой объект приводит к объекту, сериализируемому или воплощенному и присвоение дескриптора для того объекта. Последующие ссылки на тот объект кодируются как дескриптор. Используя объектные дескрипторы сохраняет совместное использование и циклические ссылки, которые происходят естественно в графах объектов. Последующие ссылки на объектное использование только дескриптор, позволяющий очень компактное представление.
Специальная обработка требуется для массивов, перечислимых констант, и объектов типа Class
, ObjectStreamClass
, и String
. Другие объекты должны реализовать любого Serializable
или Externalizable
интерфейс, который будет сохранен в или восстановлен от потока.
Примитивные типы данных пишутся потоку с методами в DataOutput
интерфейс, такой как writeInt
, writeFloat
, или writeUTF
. Отдельные байты и массивы байтов пишутся с методами OutputStream
. За исключением сериализуемых полей, примитивные данные пишутся потоку в блочных записях данных с каждой записью, снабженной префиксом маркером и индикацией относительно числа байтов в записи.
ObjectOutputStream
может быть расширен, чтобы настроить информацию о классах в потоке или заменить объекты, которые будут сериализированы. Обратитесь к annotateClass
и replaceObject
описания метода для деталей.
// Deserialize a string and date from a file. FileInputStream in = new FileInputStream("tmp"); ObjectInputStream s = new ObjectInputStream(in); String today = (String)s.readObject(); Date date = (Date)s.readObject();Сначала
InputStream
, в этом случае a FileInputStream
, необходим как исходный поток. Затем ObjectInputStream
создается что чтения из InputStream
. Затем, строка "Сегодня" и объект Даты читаются из потока. Обычно, объекты читаются с readObject
метод и примитивы читаются из потока с методами DataInput
. readObject
метод десериализовывает следующий объект в потоке и пересекает его ссылки на другие объекты рекурсивно, чтобы создать полный график сериализированных объектов.
Примитивные типы данных читаются из потока с методами в DataInput
интерфейс, такой как readInt
, readFloat
, или readUTF
. Отдельные байты и массивы байтов читаются с методами InputStream
. За исключением сериализуемых полей, примитивные данные читаются из блочных записей данных.
ObjectInputStream
может быть расширен, чтобы использовать настроенную информацию в потоке о классах или заменить объекты, которые были десериализованы. Обратитесь к resolveClass
и resolveObject
описания метода для деталей.
Каждый объект, который действует как контейнер, реализует интерфейс, который позволяет примитивы и возражает, чтобы быть сохраненным в или полученным от него. Эти интерфейсы ObjectOutput
и ObjectInput
интерфейсы, который:
Чтобы быть сохраненным в Объектном Потоке, каждый объект должен реализовать любого Serializable
или Externalizable
интерфейс:
Serializable
класс, Объектная Сериализация может автоматически сохранить и восстановить поля каждого класса объекта и автоматически обработать классы, которые развиваются, добавляя поля или супертипы. Сериализуемый класс может объявить, какие из его полей сохраняются или восстанавливаются, и запись и читают дополнительные значения и объекты.Externalizable
класс, Объектные делегаты Сериализации в полном контроле класса над его внешним форматом и как состояние супертипа (ов) сохраняется и восстанавливается.Serializable
класс, serialPersistentFields
. Это поле должно быть инициализировано с массивом ObjectStreamField
объекты, которые перечисляют имена и типы сериализуемых полей. Модификаторы для поля обязаны быть частными, статичными, и заключительными. Если значение поля является нулем или является иначе не экземпляром ObjectStreamField[]
, или если у поля нет необходимых модификаторов, то поведение состоит в том, как будто поле не было объявлено вообще. Например, следующее объявление копирует поведение по умолчанию.
class List implements Serializable { List next; private static final ObjectStreamField[] serialPersistentFields = {new ObjectStreamField("next", List.class)};
}При использовании
serialPersistentFields
чтобы определить поля Serializable для класса, больше нет ограничения, что сериализуемое поле должно быть полем в пределах текущего определения Serializable
класс. writeObject
и readObject
методы Serializable
класс может отобразить текущую реализацию класса сериализуемых полей класса, используя интерфейс, который описывается в Разделе 1.7, "Получая доступ к Сериализуемым Полям Класса." Поэтому, поля для a Serializable
класс может измениться в более позднем выпуске, пока он поддерживает отображение назад на его поля Serializable, которые должны остаться совместимыми через границы выпуска. serialPersistentFields
для внутреннего класса (хотя возможно установить это для статических задействованных классов). Для других ограничений, имеющих отношение к сериализации внутренних экземпляров класса, см. Раздел раздела 1.10, "Сериализуемый Интерфейс". @serial
, @serialField
, и @serialData
, обеспечьте способ задокументировать сериализированную форму для Сериализуемого класса в пределах исходного кода. @serial
тег должен быть помещен в комментарий javadoc для сериализуемого поля по умолчанию. Синтаксис следующие: @serial
полевое описание дополнительное полевое описание описывает значение поля и его приемлемых значений. Полевое описание может охватить многократные строки. Когда поле добавляется после начального выпуска тег @since указывает на версию, поле было добавлено. Полевое описание для @serial
обеспечивает специфичную для сериализации документацию и добавляется к комментарию javadoc для поля в пределах сериализированной документации формы.@serialField
тег привык к документу ObjectStreamField
компонент a serialPersistentFields
массив. Один из этих тегов должен использоваться для каждого ObjectStreamField
компонент. Синтаксис следующие: @serialField
полевое описание типа поля имени поля@serialData
тег описывает последовательности и типы записанных данных, или читать. Тег описывает последовательность и тип дополнительных данных, записанных writeObject
или все данные, записанные Externalizable.writeExternal
метод. Синтаксис следующие: @serialData
описание данных Когда класс объявляется Сериализуемый, сериализуемое состояние объекта определяется сериализуемыми полями (по имени и тип) плюс дополнительные данные. Дополнительные данные могут только быть записаны явно writeObject
метод a Serializable
класс. Дополнительные данные могут быть считаны Serializable
класс readObject
метод или сериализация пропустят непрочитанные дополнительные данные.
Когда класс объявляется Экстернэлизэйблом, данные, которые пишутся потоку самим классом, определяют сериализированное состояние. Класс должен определить порядок, типы, и значение каждой данной величины, которая пишется потоку. Класс должен обработать свое собственное развитие, так, чтобы он мог продолжать читать данные, записанные и данные записи, которые могут быть считаны предыдущими версиями. Класс должен скоординировать с суперклассом, сохраняя и восстанавливая данные. Расположение данных суперклассов в потоке должно быть определено.
Разработчик Сериализуемого класса должен гарантировать, что информация, сохраненная для класса, является подходящей для персистентности и следует за определенными сериализацией правилами для функциональной совместимости и развития. Развитие класса объясняется более подробно в Главе 5, "Управление версиями Сериализуемых Объектов."
Serializable
соедините интерфейсом и не сделайте никакой дальнейшей настройки. Сериализуемые поля отображаются на соответствующие поля класса, и значения или пишутся потоку от тех полей или читаются в и присваиваются соответственно. Если класс обеспечивает writeObject
и readObject
методы, механизм по умолчанию может быть вызван, вызывая defaultWriteObject
и defaultReadObject
. Когда writeObject
и readObject
методы реализуются, у класса есть возможность изменить сериализуемые значения полей прежде, чем они будут записаны или после того, как они читаются. Когда механизм по умолчанию не может использоваться, сериализуемый класс может использовать putFields
метод ObjectOutputStream
помещать значения для сериализуемых полей в поток. writeFields
метод ObjectOutputStream
помещает значения в правильном порядке, затем пишет им в поток, используя существующий протокол для сериализации. Соответственно, readFields
метод ObjectInputStream
читает значения из потока и делает их доступными для класса по имени в любом порядке. См. Раздел 2.2, "ObjectOutputStream. Класс PutField" и Раздел 3.2, "ObjectInputStream. Класс GetField." для подробного описания Сериализуемого Полевого API.
ObjectOutput
интерфейс обеспечивает абстрактный, основанный на потоке интерфейс, чтобы возразить хранению. Это расширяет интерфейс DataOutput, таким образом, те методы могут использоваться для того, чтобы записать примитивные типы данных. Объекты, которые реализуют этот интерфейс, могут использоваться, чтобы сохранить примитивы и объекты.
package java.io; public interface ObjectOutput extends DataOutput { public void writeObject(Object obj) throws IOException; public void write(int b) 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; public void close() throws IOException; }
The
writeObject
метод используется, чтобы записать объект. Брошенные ошибки отражения исключений, получая доступ к объекту или его полям, или исключениям, которые происходят в письменной форме с хранением. Если какое-либо исключение выдается, базовое хранение может быть повреждено. Если это происходит, обратитесь к объекту, который реализует этот интерфейс для получения дополнительной информации. ObjectInput
интерфейс обеспечивает абстрактный поток базируемый интерфейс, чтобы возразить извлечению. Это расширяется DataInput
взаимодействуйте через интерфейс, таким образом, те методы для того, чтобы считать примитивные типы данных доступны в этом интерфейсе.
package java.io; public interface ObjectInput extends DataInput { public Object readObject() throws ClassNotFoundException, IOException; public int read() throws IOException; public int read(byte b[]) throws IOException; public int read(byte b[], int off, int len) throws IOException; public long skip(long n) throws IOException; public int available() throws IOException; public void close() throws IOException; }
readObject
метод используется, чтобы считать и возвратить объект. Брошенные ошибки отражения исключений, получая доступ к объектам или его полям или исключениям, которые происходят в чтении от хранения. Если какое-либо исключение выдается, базовое хранение может быть повреждено. Если это происходит, обратитесь к объекту, реализовывая этот интерфейс для дополнительной информации. Serializable
интерфейс определяется, чтобы идентифицировать классы, которые реализуют сериализуемый протокол:
package java.io; public interface Serializable {};Сериализуемый класс должен сделать следующее:
serialPersistentFields
элемент, чтобы явно объявить их сериализуемый или использовать переходное ключевое слово, чтобы обозначить несериализуемые поля.)writeObject
метод, чтобы управлять, какая информация сохраняется или добавлять дополнительную информацию к потокуreadObject
метод любой, чтобы считать информацию, записанную соответствием writeObject
метод или обновить состояние объекта после того, как это было восстановленоwriteReplace
метод, чтобы позволить классу назначать замену возражает, чтобы быть записанным потокуreadResolve
метод, чтобы позволить классу определять замену возражает для объекта, только считанного из потокаObjectOutputStream
и ObjectInputStream
позвольте сериализуемые классы, на которых они работают, чтобы развиться (позвольте изменения классам, которые являются совместимыми с более ранними версиями классов). См. Раздел 5.5, "Совместимое Развитие Типа JavaTM" для информации о механизме, который используется, чтобы позволить совместимые изменения. javac
(или другие компиляторы JavaTM), чтобы реализовать внутренние классы являются зависящими от реализации и может измениться между компиляторами; различия в таких полях могут разрушить совместимость так же как привести к конфликтному значению по умолчанию serialVersionUID
значения. Имена, присвоенные локальным и анонимным внутренним классам, являются также зависящими от реализации и могут отличаться между компиляторами. Так как внутренние классы не могут объявить статические элементы кроме времени компиляции постоянные поля, они не могут использовать serialPersistentFields
механизм, чтобы определять сериализуемые поля. Наконец, потому что у внутренних классов, связанных с внешними экземплярами, нет конструкторов нулевого параметра (конструкторы таких внутренних классов неявно принимают экземпляр включения как предварительно ожидаемый параметр), они не могут реализовать Externalizable
. Ни одна из упомянутых выше проблем, однако, не применяется к статическим задействованным классам. Externalizable
интерфейс определяется следующим образом:
package java.io; public interface Externalizable extends Serializable { public void writeExternal(ObjectOutput out) throws IOException; public void readExternal(ObjectInput in) throws IOException, java.lang.ClassNotFoundException; }Класс объекта Externalizable должен сделать следующее:
java.io.Externalizable
интерфейсwriteExternal
метод, чтобы сохранить состояние объектаreadExternal
метод, чтобы считать данные, записанные writeExternal
метод от потока и восстановления состояние объектаwriteExternal
и readExternal
методы быть исключительно ответственным за формат, если внешне определенный формат пишетсяwriteExternal
и readExternal
методы общедоступны и повышают риск, что клиент может быть в состоянии записать или считать информацию в объекте кроме при использовании его методов и полей. Эти методы должны использоваться только, когда информация, сохраненная объектом, не чувствительна или когда представление этого не представляет угрозу безопасности. Externalizable
интерфейсный механизм не может использоваться для внутренних классов, и они должны реализовать Serializable
интерфейс, если они должны быть сериализированы. Несколько ограничений существуют для сериализуемых внутренних классов также, однако; см. Раздел 1.10, "Сериализуемый Интерфейс", для полного перечисления. writeReplace
метод, чтобы позволить классу назначать замену возражает, чтобы быть записанным потокуreadResolve
метод, чтобы позволить классу определять замену возражает для объекта, только считанного из потокаObjectOutputStream
пишет значение, возвращенное перечислимой константой name
метод. Десериализовывать перечислимую константу, ObjectInputStream
читает постоянное имя из потока; десериализованная константа тогда получается, вызывая java.lang.Enum.valueOf
метод, передавая перечислимый тип константы наряду с полученным постоянным именем как параметры. Как другое сериализуемое или объекты externalizable, перечислимые константы могут функционировать как цели обратных ссылок, появляющихся впоследствии в потоке сериализации. Процесс, которым сериализируются перечислимые константы, не может быть настроен: любой специфичный для класса writeObject
, readObject
, readObjectNoData
, writeReplace
, и readResolve
методы, определенные перечислимыми типами, игнорируются во время сериализации и десериализации. Точно так же любой serialPersistentFields
или serialVersionUID
полевые объявления также игнорируются - у всех перечислимых типов есть фиксированный serialVersionUID
из 0L
. Документирование сериализуемых полей и данных для перечислимых типов является ненужным, так как нет никакого изменения в типе отправленных данных.
Самый легкий метод должен отметить поля, которые содержат уязвимые данные как частный переходный процесс. Переходные поля не являются персистентными и не будут сохранены никаким механизмом персистентности. Отмечание поля будет препятствовать тому, чтобы состояние появилось в потоке и от того, чтобы быть восстановленным во время десериализации. Начиная с записи и чтения (частных полей) не может быть заменен за пределами класса, переходные поля класса безопасны.
Особенно чувствительные классы не должны быть сериализированы вообще. Чтобы выполнить это, объект не должен реализовать ни одного Serializable
или Externalizable
интерфейс.
Некоторые классы могут счесть выгодным, чтобы позволить писать и читать, но определенно обработать и подтвердить состояние, поскольку это десериализовывается. Класс должен реализовать writeObject
и readObject
методы, чтобы сохранить и восстановить только соответствующее состояние. Если доступ должен быть лишен, бросая a NotSerializableException
предотвратит дальнейший доступ.