Содержание | Предыдущая | Следующая


ГЛАВА 7

Пакеты

Программы на языке Ява организованы как наборы пакетов. Каждый пакет имеет собственный набор имен для типов, который помогает предотвращать конфликты между именами. Тип доступен (§6.6) вне пакета, в котором он объявлен, только если этот тип объявлен как public.

Структура наименования для пакетов является иерархической (§7.1). Элементы пакета - это классовые и интерфейсные типы (§7.6), которые объявлены в модулях компиляции пакета, и подпакетах, которые могут содержать модули компиляции и их собственные подпакеты.

Пакет можно сохранить в файловой системе (§7.2.1) или в базе данных (§7.2.2). Пакеты, которые сохранены в файловой системе, имеют некоторые ограничения на организацию их модулей компиляции для более легкого нахождения классов. В любом случае, набор пакетов, доступных программе на Яве, определен базовой системой, но всегда должен включать по крайней мере три стандартных пакета java.lang, java.util, и java.io как определено в главах 20, 21, и 22. В большинстве вычислительных сред, стандартные пакеты java.applet, java.awt, и java.net, которые не описаны в этой спецификации, являются также доступными программам на Яве.

Пакет состоит из ряда модулей компиляции (§7.3). Модуль компиляции автоматически имеет доступ ко всем типам, объявленным в пакете и также автоматически импортирует каждый из типов, объявленных в предопределенном пакете java.lang.

Модуль компиляции имеет три части, каждая из которых необязательная:

 

Для маленьких программ и случайной разработки, пакет может не иметь имени (§7.4.2) или иметь простое имя, но если предполагается широкое использование кода Явы, желательно использовать уникальные имена пакетов (§7.7). Это может предотвратить конфликты, которые иначе бы произошли, если бы случилось так, что две группы выбрали одно и то же имя пакета, и эти пакеты позже использовались бы в одной и той же программе.

7.1 Члены пакета

Пакет может иметь члены любого или обоих из следующих видов:

 

Например, в стандартном Java Application Programming Interface:

 

Если полностью квалифицированное имя (§6.7) пакета - P, а Q - подпакет P, то P.Q - это полностью квалифицированное имя подпакета.

Подпакеты пакета java: lang, util, и io (чьи полностью квалифицированные имена соответственно java.lang, java.util, и java.io) есть стандартная часть каждой реализации Явы и определены в Главах 20, 21, и 22. Многие реализации Явы будут включать полный набор пакетов Явы, определенный в сериях книг The Java Application Programming Interface.

Пакет не может содержать объявление типа и подпакета с тем же самым именем, иначе возникнет ошибка времени компиляции. Вот некоторые примеры:

Иерархическая структура именования пакетов нужна для того, чтобы была удобной организация связанных пакетов стандартным способом, и запрещается, чтобы пакет имел подпакет с тем же самым простым именем, что и имя типа, объявленного в этом пакете. Не существует никакой специальной связи в языке Ява между пакетом, именованным oliver и другим пакетом oliver.twist, или между пакетами, именованными evelyn.wood и evelyn.Waugh. Например, код в пакете, именованном oliver.twist не имеет лучшего доступа к типам, объявленным внутри пакета oliver, чем код в любом другом пакете.

7.2 Базовая система для пакетов

Каждая базовая система Явы определяет, в каком виде пакеты, модули компиляции, и подпакеты созданы и сохранены; какие имена верхнего уровня пакета находятся в области видимости в определенный момент компиляции; и какие пакеты доступны.

Пакеты могут хранится в локальной файловой системе в простых реализациях Явы. Другие реализации могут использовать распределенную файловую систему или некоторую форму базы данных, чтобы хранить исходные тексты программ на Яве и/или двоичный код.

7.2.1 Хранение пакетов в файловой системе

Как чрезвычайно простой пример, все пакеты Явы (исходный текст и двоичный код) могут быть сохранены в одном каталоге и в его подкаталогах. Каждый непосредственный подкаталог этого каталога мог бы представлять пакет верхнего уровня, то есть тот, чье полностью квалифицированное имя состоит из одиночного простого имени. Каталог мог бы содержать следующие непосредственные подкаталоги:

 

COM
gls
jag
java
wnj

где каталог java содержал бы пакеты стандартного Java Application Programming Interface, которые являются частью каждой стандартной системы; каталоги jag, gls, и wnj могли бы содержать пакеты, которые три автора этой спецификации создали для их персонального использования и совместного использования друг с другом внутри этой малой группы; и каталог COM содержал бы пакеты, заказываемые компаниями, использующими соглашения, описанные в §7.7, чтобы генерировать уникальные имена для их пакетов.

В продолжении примера, каталог java возможно содержал бы по крайней мере следующие подкаталоги:

 

applet	
awt
io
lang
net
util

cоответствующие стандартным пакетам java.applet, java.awt, java.io, java.lang, java.net, и java.util, которые определены как часть стандартного Java Application Programming Interface.

Продолжая пример, если бы мы заглянули внутрь каталога util, мы бы увидели следующие файлы:

BitSet.java										Observable.java
BitSet.class										Observable.class
Date.java										Observer.java
Date.class										Observer.class
Dictionary.java										Properties.java
Dictionary.class									Properties.class
EmptyStackException.java								Random.java
EmptyStackException.class								Random.class
Enumeration.java									Stack.java
Enumeration.class									Stack.class
Hashtable.java										StringTokenizer.java
Hashtable.class										StringTokenizer.class
NoSuchElementException.java								Vector.java
NoSuchElementException.class								Vector.class

Где каждый из .java файлов содержит исходный текст модуля компиляции (§7.3) который содержит определение класса или интерфейса, чья двоичная форма содержится в соответствующем файле с расширением .class.

При этой простой организации пакетов, реализация Явы трансформировала бы имя пакета в путь, связывая компоненты имени пакета, размещая разделитель имени файла (индикатор каталога) между смежными компонентами. Например, если эта простая организация использовалась на системе UNIX, где разделитель имен файла есть /, имя пакета

jag.scrabble.board

было бы преобразовано в имя каталога

jag/scrabble/board

и:

COM.Sun.sunsoft.DOE

было бы преобразовано в имя каталога

COM/Sun/sunsoft/DOE

Фактически, стандартный JavaSoft Java Developer's Kit на UNIX отличается от самой простой дисциплины, описанной здесь только тем, что он имеет системную переменную CLASSPATH, которая определяет набор каталогов, каждый из которых обрабатывается подобно одиночному каталогу, описанному здесь. Эти каталоги ищут для определения именованных пакетов и типов.

Компонент имени пакета или имени класса может содержать символ, который не может появляться в имени обычного каталога файловой системы, такой как символ Unicode на системе, которая допускает использование только символов ASCII в именах файла. По стандарту, символ может быть использован, при использовании символа @ после которого идут четыре шестнадцатеричные цифры, дающие числовое значение символа, как в последовательности \uxxxx (§3.3), таким образом имя пакета:

children.activities.crafts.papierM\u00e2ch\u00e9

которое может быть также записано, используя Unicode как:

children.activities.crafts.papierMache

может быть преобразовано в имя каталога

children/activities/crafts/papierM@00e2ch@00e9

Если символ @ – недопустимый символ в имени файла для данной файловой системы, то какой-то другой символ, который не допустим в Яве, может использоваться вместо него.

7.2.2 Хранение пакетов в базе данных

Базовая система может хранить пакеты и их модули компиляции и подпакеты в базе данных.

Ява разрешает, чтобы такая база данных ослабила ограничения (§7.6) на модули компиляции в реализациях с файловой основой. Например, при использовании базы данных для хранения пакетов, нет ограничения на число классов или интерфейсов, объявленных с модификатором public, в каждом модуле компиляции. Системы, которые используют базу данных, должны, однако, обеспечить опцию, чтобы преобразовать программу на Яве в форму, которая удовлетворяет условиям ограничений, для целей экспорта реализации с файловой основой.

7.3 Модули компиляции

Модуль компиляции - это начальный символ (§2.1) для синтаксической грамматики (§2.3) программ на Яве. Он определен, используя следующие продукции:

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

Модуль компиляции состоит из трех частей, каждая из которых необязательная:

Каждый модуль компиляции автоматически и неявно импортирует всякое имя типа с модификатором public, объявленное в предопределенном пакете java.lang, так, чтобы имена всех типов были доступны как простые имена, как описано в §7.5.3.

7.4 Объявления пакета

Объявление пакета появляется внутри модуля компиляции, чтобы указать пакет, которому данный модуль принадлежит. Модуль компиляции, который не содержит никакого объявления пакета есть часть неименованного пакета.

7.4.1 Именованные пакеты

Объявление пакета в модуле компиляции определяет имя (§6.2) пакета, которому модуль компиляции принадлежит.

Имя пакета, упомянутое в объявлении пакета должно быть полностью квалифицированным именем (§6.7) пакета.

Если тип T объявлен в модуле компиляции пакета, чье полностью квалифицированное имя есть P, то полностью квалифицированное имя типа есть P.T; таким образом в примере:

package wnj.points;
class Point { int x, y; }

полностью квалифицированное имя класса Point есть wnj.points.Point.

7.4.2 Неименованные пакеты

Модуль компиляции, который не содержит никакого объявления пакета есть часть неименованного пакета. Например, модуль компиляции:


class FirstCall {
	public static void main(String[] args) {
		System.out.println("Mr. Watson, come here. "
									+ "I want you.");
	}
}

определяет очень простой модуль компиляции как часть неименованного пакета.

Система Явы должна поддерживать по крайней мере один неименованный пакет; но она может поддерживать и более одного, но этого не требуется. Какие модули компиляции находятся в каждом неименованном пакете определяется базовой системой.

В системах, которые используют иерархическую файловую систему для хранения пакетов, основной задачей является связать неименованный пакет с каждым каталогом; только один неименованный пакет доступен в данный момент, а именно тот, который связан с "текущим рабочим каталогом". Точное значение "текущего рабочего каталога" зависит от базовой системы.

Неименованные пакеты обеспечиваются Явой главным образом для удобства при разработке маленьких или временных прикладных программ или при начальной стадии разработки.

При использовании неименованных пакетов должны быть приняты меры предосторожности. Модуль компиляции в именованном пакете может импортировать тип из неименованного пакета, но тогда компилируемая версия этого модуля компиляции будет правильно затем работать только, когда тот неименованный пакет является "текущим". По этой причине, настоятельно рекомендуется, чтобы модули компиляции именованных пакетов никогда не импортировали типы из неименованных пакетов. Также рекомендуется, чтобы любой тип, объявленный в неименованном пакете, не был объявлен с модификатором public, чтобы предохранить его от случайного импорта именованным пакетом.

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

7.4.3 Область действия и скрытие имени пакета

Какие имена пакета верхнего уровня находятся в области действия, (§6.3, §6.5)определяется в соответствии с соглашениями базовой системы.

Имена пакетов никогда не скрывают другие имена.

7.4.4 Доступ к членам пакета

Базовая система определяет, разрешен ли доступ к членам пакета. Пакет java должен всегда быть доступен вместе с его стандартными подпакетами lang, io, и util .

Настоятельно рекомендуется, чтобы защита файловой системы или базы данных, используемых для сохранения программ на Яве, была установлена так, чтобы все модули компиляции пакета были доступны.

7.5 Объявление импорта

Объявление импорта (import) разрешает использовать простые имена, объявленные в другом пакете (§6.2), состоящие из одиночного идентификатора. Без использования соответствующего объявления import, единственный способ обратиться к типу, объявленному в другом пакете состоит в том, чтобы использовать полностью квалифицированное имя (§6.7).

объявление одиночного импорта типа (§7.5.1) импортирует одиночный тип, упоминая полностью квалифицированное имя. Объявление импорта типа по шаблону(§7.5.2) импортирует все типы именованного пакета, объявленные public.

Объявление import делает типы доступными по их простым именам только внутри модуля компиляции, который содержит объявление import. Область действия имени (имен) не включает в себя оператор package, другие import-операторы текущего модуля компиляции, или другие модули компиляции в том же пакете. Пожалуйста для пояснения смотрите пример из. §7.5.4.

7.5.1 Объявление одиночного импорта типа

Объявление одиночного импорта типа импортирует простой тип, давая полностью квалифицированное имя и делая его доступным под простым именем в объявлениях класса и интерфейса в модуле компиляции.

TypeName должно быть полностью квалифицированным именем классового или интерфейсного типа; если такой тип не существует, то происходит ошибка времени компиляции. Если данного типа нет в текущем пакете, то он должен быть доступным (§6.6); для этого он должен быть объявлен public (§8.1.2, §9.1.2), иначе происходит ошибка времени компиляции.

Пример:

import java.util.Vector;

делает простое имя Vector доступным внутри объявлений классов и интерфейсов в модуле компиляции. Таким образом, простое имя Vector ссылается на тип Vector в пакете java.util во всех местах, где оно не скрыто (§6.3) объявлением поля, параметра, или локальной переменной с тем же самым именем.

Если два import-объявления простого типа в том же самом модуле компиляции пытаются импортировать типы с одним и тем же простым именем, то происходит ошибка времени компиляции, за исключением случая, если два типа являются одним и тем же типом, тогда повторное объявление игнорируется. Если другой тип с тем же самым именем иначе объявлен в текущем модуле компиляции, за исключением объявления импорта типа по шаблону (§7.5.2), то происходит ошибка времени компиляции.

Так в программе:

import java.util.Vector;

class Vector { Object[] vec; }

возникает ошибка времени компиляции из-за двойного объявления Vector, также как :

import java.util.Vector;

import myVector.Vector;

где myVector - пакет, содержащий модуль компиляции:

package myVector;

public class Vector { Object[] vec; }

Компилятор следит за типами по их полностью квалифицированным именам (§6.7). Простые имена и cоставные имена могут использоваться равнозначно всякий раз, когда они оба доступны.

Обратите внимание, что импорт не может импортировать подпакет, только тип. Например, ничего не выйдет, если пробовать импортировать java.util и затем использовать имя util.Random, чтобы обратиться к типу java.util.Random:

import java.util;										// неправильно: ошибка времени компиляции

class Test { util.Random generator; }

7.5.2 Объявление импорта типа по шаблону

Объявление импорта типа по шаблону позволяет всем public типам, объявленным в пакете, имеющем полностью квалифицированное имя, быть импортируемыми, если это необходимо.

Если назвать пакет, который не доступен (§6.6), как определено Ява-системой (§7.2), то это ошибка времени компиляции для объявление импорта типа по шаблону. Два или больше объявления импорта типа по шаблону в одном и том же модуле компиляции могут использовать тот же самый пакет; это то же самое, как если бы имелось ровно одно такое объявление. Ошибки времени компиляции не возникает, если указать имя текущего пакета или java.lang в объявлении импорта типа по шаблону, даже если они уже импортируются; дубликат объявления импорта типа по шаблону игнорируется.

Пример:

import java.util. *;

делает простые имена всех public-типов, объявленных в пакете java.util доступными внутри класса и интерфейса в модуле компиляции. Таким образом, простое имя Vector относится к типу Vector в пакете java.util во всех местах, где оно не скрыто (§6.3) import-объявлением простого типа, чье простое имя есть Vector; типом, именованным Vector и объявленным в пакете, которому принадлежит модуль компиляции; или объявлением поля, параметра, или локальной переменной, имеющими имя Vector. (Это было бы необычно, если бы какое-нибудь из этих условий произошло.)

7.5.3 Импорт по умолчанию

Каждый модуль компиляции автоматически импортирует каждое имя public-типа, объявленное в предопределенном пакете java.lang, как будто в начале каждого модуля компиляции помещено объявление:

import java.lang. *;

сразу же после заголовка пакета

Полная спецификация java.lang дана в главе 20. В java.lang определены следующие public- типы:

AbstractMethodError									LinkageError
ArithmeticException									Long
ArrayStoreException									Math
Boolean											NegativeArraySizeException
Character										NoClassDefFoundError
Class											NoSuchFieldError
ClassCastException									NoSuchMethodError
ClassCircularityError									NullPointerException
ClassFormatError									Number
ClassLoader										NumberFormatException
ClassNotFoundException									Object
CloneNotSupportedException								OutOfMemoryError
Cloneable										Process
Compiler										Runnable
Double											Runtime
Error											RuntimeException
Exception										SecurityException
ExceptionInInitializerError								SecurityManager
Float											StackOverflowError
IllegalAccessError									String
IllegalAccessException									StringBuffer
IllegalArgumentException								System
IllegalMonitorStateException								Thread
IllegalThreadStateException								ThreadDeath
IncompatibleClassChangeError								ThreadGroup
IndexOutOfBoundsException								Throwable
InstantiationError									UnknownError
InstantiationException									UnsatisfiedLinkError
Integer											VerifyError
InternalError										VirtualMachineError
InterruptedException

7.5.4 Странный пример

Имена пакетов и имена типов обычно различны по соглашениям, описанным в §6.8. Однако, в придуманном примере, где имеется нетрадиционно именованный пакет Vector, который объявляет public класс, именованный Mosquito:

package Vector;

public class Mosquito { int capacity; }

и затем модуль компиляции:

package strange.example;


import java.util.Vector;


import Vector.Mosquito;


class Test {
	public static void main(String[] args) {
		System.out.println(new Vector().getClass());
		System.out.println(new Mosquito().getClass());
	}
}

import-объявление простого типа (§7.5.1), импортирующее класс Vector из пакета java.util, допускает, чтобы имя пакета Vector от появления и правильного распознавания в последующих объявлениях импорта. Пример выводит:

class java.util.Vector

class Vector.Mosquito

7.6 Объявления типа

Объявление типа объявляет классовый (§8) или интерфейсный (§9) типы:

Компилятор Явы должен игнорировать дополнительные ";" лексемы, появляющиеся на уровне объявлений типа. Лишние точки с запятой разрешаются в Яве исключительно как уступка программистам на C++, которые используют для записи:

class date { int month, day, year; };

( В C++, но не в Яве, любой может использовать отделенный запятой список идентификаторов, чтобы объявить переменные между "}" и ";".). Дополнительные точки с запятой не должны использоваться в новом коде Явы. Программное обеспечение, которое переформатирует код Явы, может удалить их.

По умолчанию, типы, объявленные в пакете доступны только внутри модулей компиляции этого пакета, но тип может быть объявлен public, чтобы предоставить доступ к типу из кода в других пакетах (§6.6, §8.1.2, §9.1.2).

Реализация Явы должна следить за типами внутри пакетов по их полностью квалифицированным именам (§6.7). Различные способы именования типа должны быть расширены до полностью квалифицированных имен, чтобы удостовериться, что такие имена распознаны как ссылка на тот же самый тип. Например, если модуль компиляции содержит import-объявление простого типа (§7.5.1):

import java.util.Vector;

то внутри этого модуля компиляции простое имя Vector и полностью квалифицированное имя java.util.Vector одного и того же типа.

Когда пакеты Явы хранятся в файловой системе (§7.2.1), то происходит ошибка времени компиляции, если тип не найден в файле под именем, составленным из имени типа плюс расширение ( .java или .jav), если любое из следующих утверждений истинно:

 

Это ограничение подразумевает, что должен быть по крайней мере один такой тип на каждый модуль компиляции. Это ограничение делает более легким для компилятора Явы и виртуальной машины Явы нахождение именованного класса внутри пакета; например, исходный код для public типа wet.sprocket.Toad должен находиться в файле Toad.java в каталоге wet/ sprocket, и соответствующий объектный код будет найден в файле Toad.class в том же самом каталоге.

Если пакеты Явы хранятся в базе данных (§7.2.2), то система Явы не обязана накладывать такие ограничения.

Практически, многие программисты на Яве предпочитают размещать каждый классовый или интерфейсный тип в его собственный модуль компиляции, несмотря на то, является ли он общим или на него ссылаются при помощи кода в других модулях компиляции.

7.7 Уникальные имена пакетов

Разработчики должны что-то предпринять, чтобы избежать возможности для двух пакетов иметь одно имя, выбирая уникальные имена пакета для пакетов. Это позволяет пакетам быть легко и автоматически устанавливаемыми и каталогизируемыми. Этот раздел определяет стандартное соглашение, не предписанное компилятором Явы, для создания таких уникальных имен пакета. Система Явы стремится обеспечить автоматическое преобразование локальных и случайных имен пакета в уникальные имена, описанные здесь.

Если уникальные имена пакетов не используются, то конфликты имен пакетов могут возникать далеко от места создания любого из находящихся в противоречии пакетов. Это может создать неразрешимую ситуацию для пользователя или программиста. Класс ClassLoader (§20.14) из стандартного окружения виртуальной машины Явы может быть использован, чтобы изолировать пакеты с одним и тем же именем друг от друга в тех случаях, где пакеты вынуждены взаимодействовать, но не совсем понятным способом.

Когда вы создаете уникальное имя пакета, то сначала вы пишите имя домена в Internet, которому вы принадлежите (или имя организации, которая имеет к нему принадлежит ), например, Sun.COM. Затем вы переставляете компонент за компонентом, чтобы получить в этом примере COM.Sun, и используете его как префикс для ваших имен пакета, используя соглашение, разработанное внутри вашей организации.

Такое соглашение могло бы определять, что некоторый компонент имени каталога может означать отделение, проект, машину, или имя входа в систему. Некоторые примеры:

 

COM.Sun.sunsoft.DOE
COM.Sun.java.jag.scrabble
COM.Apple.quicktime.v2
EDU.cmu.cs.bovik.cheese
GOV.whitehouse.socks.mousefinder

 

Первый компонент уникального имени пакета всегда пишется заглавными буквами ASCII и должен быть одним из имен верхнего уровня, в настоящее время COM, EDU, GOV, МIL, NET, ORG, или одного из двухбуквенных английских кодов, идентифицирующих страны как определено в ISO Standard 3166, 1981. Для подробной информации, обратитесь к документам, хранящимся в ftp://rs.internic.net/rfc, например, rfc920.txt и rfc1032.txt.

Имя пакета не обязательно означает, где пакет сохранен в Internet; например, пакет, именованный EDU.cmu.cs.bovik.cheese не обязательно доступен из адреса Internet cmu.EDU или из cs.cmu.EDU или из bovik.cs.cmu.EDU. Соглашение в Яве для создания уникальных имен пакета - просто способ добавления к существующему, широко известного уникального имени вместо того, чтобы создавать отдельную регистрацию для имени пакета в Яве.

Если вам нужно получить новое имя домена в Internet, вы можете взять анкету из ftp://ftp.internic.net и отправить предложенные полные формы по электронной почте в domreg@internic.net. Чтобы выяснять, каковы в настоящее время зарегистрированные имена областей, вы можете подсоединиться к rs.internic.net и использовать средство whois.


Содержание | Предыдущая | Следующая