Эккель Брюс
Шрифт:
Если в списке файлов имеется каталог, то его содержимое вместе с подкаталогами и всеми файлами автоматически помещается в файл JAR. Информация о пути файлов также сохраняется.
Несколько примеров наиболее распространенных вариантов запуска программы jar:
jar cf myJarFile jar * class
Команда создает файл JAR с именем myJarFile.jar, в котором содержатся все файлы классов из текущего каталога, с автоматически созданным манифестом:
jar cmf myJarFile jar myManifestFile mf * class
Почти идентична предыдущей команде, за одним исключением — в полученный файл JAR включается пользовательский манифест из файла myManifest-File.mf:
jar tf myJarFile jar
Вывод содержимого (списка файлов) архива myJarFile.jar:
jar tvf myJarFile jar
К предыдущей команде добавлен параметр v для получения более подробной информации о файлах, содержащихся в архиве myJarFile.jar:
jar cvf myApp jar audio classes image
Предполагается, что audio, classes и image — это каталоги, содержимое которых включается в файл myApp.jar. Благодаря параметру v в процессе сжатия выводится дополнительная информация об упаковываемых файлах.
Инструмент jar не обладает возможностями архиватора zip. Например, он не позволяет добавлять или обновлять файлы в уже существующем архиве JAR. Также нельзя перемещать файлы и удалять их после перемещения. Но при этом созданный файл JAR всегда читается инструментом jar на другой платформе (архиваторы zip о такой совместимости могут только мечтать).
Сериализация объектов
Сериализация (serialization) объектов Java позволяет вам взять любой объект, реализующий интерфейс Serializable, и превратить его в последовательность байтов, из которой затем можно полностью восстановить исходный объект. Сказанное справедливо и для сетевых соединений, а это значит, что механизм сериализации автоматически компенсирует различия между операционными системами. То есть можно создать объект на машине с ОС Windows, превратить его в последовательность байтов, а затем послать их по сети на машину с ОС UNIX, где объект будет корректно воссоздан. Вам не надо думать о различных форматах данных, порядке следования байтов или других деталях.
Сама по себе сериализация объектов интересна потому, что с ее помощью можно осуществить легковесное долговременное хранение (lightweight persistence). Вспомните: это означает, что время жизни объекта определяется не только временем выполнения программы — объект существует и между запусками программы. Можно взять объект и записать его на диск, а после, при другом запуске программы, восстановить его в первоначальном виде и таким образом получить эффект «живучести». Причина использования добавки «легковесное» такова: объект нельзя определить как «постоянный» при помощи некоторого ключевого слова, то есть долговременное хранение напрямую не поддерживается языком (хотя вероятно, такая возможность появится в будущем). Система выполнения не заботится о деталях сериализации — вам приходится собственноручно сериализовывать и восстанавливать объекты вашей программы. Если вам необходим более серьезный механизм сериализации, попробуйте библиотеку Java JDO или инструмент, подобный Hibernate net).
Механизм сериализации объектов был добавлен в язык для поддержки двух расширенных возможностей. Удаленный вызов методов Java (RMI) позволяет работать с объектами, находящимися на других компьютерах, точно так же, как и с теми, что существуют на вашей машине. При посылке сообщений удаленным объектам необходимо транспортировать аргументы и возвращаемые значения, а для этого используется сериализация объектов.
Сериализация объектов также необходима визуальным компонентам Java-Bean. Информация о состоянии визуальных компонентов обычно изменяется во время разработки. Эту информацию о состоянии необходимо сохранить, а затем, при запуске программы, восстановить; данную задачу решает сериализация объектов.
Сериализовать объект достаточно просто, если он реализует интерфейс Seri-alizable (это интерфейс для самоидентификации, в нем нет ни одного метода). Когда в язык был добавлен механизм сериализации, во многие классы стандартной библиотеки внесли изменения так, чтобы они были готовы к сериализации. К таким классам относятся все классы-оболочки для простейших типов, все классы контейнеров и многие другие. Даже объекты Class, представляющие классы, можно сериализовать.
Чтобы сериализовать объект, требуется создать выходной поток Output-Stream, который нужно вложить в объект ObjectOutputStream. По сути, вызов метода writeObject осуществляет сериализацию объекта, и далее вы пересылаете его в выходной поток данных OutputStream. Для восстановления объекта необходимо надстроить объект ObjectlnputStream для входного потока InputStream, а затем вызвать метод readObject. Как обычно, такой метод возвращает ссылку на обобщенный объект Object, поэтому после вызова метода следует провести нисходящее преобразование для получения объекта нужного типа.
Сериализация объектов проводится достаточно разумно и в отношении ссылок, имеющихся в объекте. Сохраняется не только сам образ объекта, но и все связанные с ним объекты, все объекты в связанных объектах, и т. д. Это часто называют «паутиной объектов», к которой можно присоединить одиночный объект, а также массив ссылок на объекты и объекты-члены. Если бы вы создавали свой собственный механизм сериализации, отслеживание всех присутствующих в объектах ссылок стало бы весьма нелегкой задачей. Однако в Java никаких трудностей со ссылками нет — судя по всему, в этот язык встроен достаточно эффективный алгоритм создания графов объектов. Следующий пример проверяет механизм сериализации: мы создаем цепочку связанных объектов, каждый из которых связан со следующим сегментом цепочки, а также имеет массив ссылок на объекты другого класса с именем Data:
// io/Worm java
// Тест сериализации объектов
import java.io.*;
import java util *;
import static net mindview util.Print.*;
class Data implements Serializable { private int n;
public Data(int n) { this n = n, }
public String toStringO { return Integer toString(n); }
}
public class Worm implements Serializable {
private static Random rand = new Random(47); private Data[] d = {
new Data(rand.nextlnt(10)). new Data(rand nextlnt(lO)), new Data(rand nextlnt(lO))