Spec-Zone.ru › Java Language Specification 7

Глава 7. Пакеты

Содержание

7.1. Члены пакета
7.2. Поддержка пакетов хостом
7.3. Единицы компиляции
7.4. Объявления пакетов
7.4.1. Именные пакеты
7.4.2. Безымянные пакеты
7.4.3. Наблюдаемость пакета
7.5. Объявления импорта
7.5.1. Объявления импорта одного типа
7.5.2. Объявления импорта типа по требованию
7.5.3. Объявления импорта одного статического члена
7.5.4. Объявления импорта статических членов по требованию
7.6. Объявления типов верхнего уровня

Программы организованы как наборы пакетов. Каждый пакет имеет свой набор имён для типов, что помогает предотвратить конфликты имён.

Тип верхнего уровня доступен (§6.6) за пределами пакета, который его объявляет, только если тип объявлен public.

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

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

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

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

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

Членами пакета являются его подпакеты и все типы классов верхнего уровня (§7.6, §8) и типы интерфейсов верхнего уровня (§9), объявленные во всех единицах компиляции (§7.3) пакета.

Например, в API платформы Java SE:

  • Пакет java имеет подпакеты awt, applet, io, lang, net и util, но не содержит единиц компиляции.

  • Пакет java.awt имеет подпакет с именем image, а также ряд единиц компиляции, содержащих объявления типов классов и интерфейсов.

Если полное имя (§6.7) пакета — P, и Q является подпакетом P, то P.Q — полное имя подпакета и, кроме того, обозначает пакет.

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

Вот несколько примеров:

  • Поскольку пакет java.awt имеет подпакет image, он не может (и не содержит) объявления класса или типа интерфейса с именем image.

  • Если существует пакет с именем mouse и тип-член Button в этом пакете (который затем может обозначаться как mouse.Button), то не может быть никакого пакета с полным именем mouse.Button или mouse.Button.Click.

  • Если com.nighthacks.java.jag — полное имя типа, то не может быть никакого пакета, чьё полное имя — либо com.nighthacks.java.jag, либо com.nighthacks.java.jag.scrabble.

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


package vector;
public class Vector { Object[] vec; }

который содержит класс public с именем Vector, даже если пакет java.util также объявляет класс с именем Vector. Эти два типа классов различны, что отражается в том, что у них разные полные имена (§6.7). Полное имя этого примера Vector — vector.Vector, тогда как java.util.Vector — полное имя класса Vector, включённого в платформу Java SE. Поскольку пакет vector содержит класс с именем Vector, он не может также иметь подпакет с именем Vector.

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

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

END_OF_DOCUMENT_MARKER

7.2. Поддержка пакетов хост-системой

Каждая хост-система определяет, как создаются и хранятся пакеты и единицы компиляции.

Каждая хост-система также определяет, какие единицы компиляции наблюдаемы (§7.3) в конкретной компиляции. Наблюдаемость единиц компиляции, в свою очередь, определяет, какие пакеты наблюдаемы и какие пакеты находятся в области видимости.

В простых реализациях платформы Java SE пакеты и единицы компиляции могут храниться в локальной файловой системе. Другие реализации могут хранить их с помощью распределённой файловой системы или какой-либо базы данных.

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

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

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

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

Каталог может содержать следующие непосредственные подкаталоги:

com
gls
jag
java
wnj

где каталог java будет содержать пакеты платформы Java SE; каталоги jag, gls и wnj могут содержать пакеты, созданные тремя из авторов этого спецификации для личного использования и для совместного использования в этой небольшой группе; и каталог com будет содержать пакеты, полученные от компаний, которые использовали соглашения, описанные в §6.1, для генерации уникальных имён для своих пакетов.

Продолжая пример, каталог java будет содержать, среди прочего, следующие подкаталоги:

applet
awt
io
lang
net
util

соответствующие пакетам java.applet, java.awt, java.io, java.lang, java.net и java.util, которые определены как часть API платформы Java SE.

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

BitSet.java        Observable.java
BitSet.class       Observable.class
Date.java          Observer.java
Date.class         Observer.class
...

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

В рамках этой простой организации пакетов реализация платформы Java SE преобразует имя пакета в имя пути путём конкатенации компонентов имени пакета, помещая разделитель имён файлов (индикатор каталога) между смежными компонентами.

Например, если эта простая организация использовалась в операционной системе, где разделитель имён файлов — /, имя пакета:

jag.scrabble.board

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

jag/scrabble/board

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

Согласно этому соглашению, имя пакета:

children.activities.crafts.papierM\u00e2ch\u00e9

которое также можно записать с помощью полного Юникода, как:

children.activities.crafts.papierMâché

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

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

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

7.3. Единицы компиляции

CompilationUnit — это целевой символ (§2.1) для синтаксической грамматики (§2.3) программ на Java. Она определяется следующими продукциями:


CompilationUnit:
PackageDeclarationopt ImportDeclarationsopt TypeDeclarationsopt

ImportDeclarations:
ImportDeclaration
ImportDeclarations ImportDeclaration

TypeDeclarations:
TypeDeclaration
TypeDeclarations TypeDeclaration

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

  • Декларация package (§7.4), указывающая полное квалифицированное имя (§6.7) пакета, к которому относится единица компиляции.

    Единица компиляции, у которой нет декларации package, является частью безымянного пакета (§7.4.2).

  • Декларации import (§7.5), которые позволяют ссылаться на типы из других пакетов и static члены типов, используя их простые имена.

  • Декларации типов верхнего уровня (§7.6) классов и интерфейсов.

Каждая единица компиляции неявно импортирует каждое имя типа public, объявленное в предопределённом пакете java.lang, как если бы декларация import java.lang.*; появилась в начале каждой единицы компиляции сразу после любого оператора package. В результате, имена всех этих типов доступны в качестве простых имён в каждой единице компиляции.

Все единицы компиляции предопределённого пакета java и его подпакетов lang и io всегда наблюдаемы.

Для всех остальных пакетов хост-система определяет, какие единицы компиляции наблюдаемы.

Наблюдаемость единицы компиляции влияет на наблюдаемость её пакета (§7.4.3).

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

END_OF_DOCUMENT_MARKER

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

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

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

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


PackageDeclaration:
Annotationsopt package PackageName ;

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

Имя пакета в объявлении пакета гарантирует, что существует наблюдаемый пакет с указанным каноническим именем, и что он не подлежит правилам в §6.5.3 для определения значения имени пакета.

Область действия и перекрытие объявления пакета указаны в §6.3 и §6.4.

Ключевое слово package может быть необязательно предваряемо модификаторами аннотаций. Если аннотация a (§9.7) на объявлении пакета соответствует типу аннотации T (§9.6), и T имеет (мета-)аннотацию m, которая соответствует java.lang.annotation.Target, то m должен иметь элемент, значение которого равно java.lang.annotation.ElementType.PACKAGE, в противном случае произойдёт ошибка времени компиляции.

Для данного пакета разрешено не более одного объявления пакета с аннотациями.

Способ, которым это ограничение применяется, по необходимости должен варьироваться от реализации к реализации. Для реализаций, основанных на файловой системе, настоятельно рекомендуется следующий подход: единственное объявление пакета с аннотациями, если оно существует, размещается в исходном файле, называемом package-info.java, в каталоге, содержащем исходные файлы пакета. Этот файл не содержит исходный код класса, называемого package-info.java; на самом деле это было бы незаконно, так как package-info не является допустимым идентификатором. Обычно package-info.java содержит только объявление package, непосредственно перед которым находятся аннотации к пакету. Хотя технически этот файл может содержать исходный код одного или нескольких пакетов частного доступа (доступ по умолчанию), это будет очень плохим стилем.

Рекомендуется, чтобы package-info.java, если оно присутствует, занимало место package.html для javadoc и других подобных систем генерации документации. Если этот файл существует, инструмент генерации документации должен искать комментарий к документации пакета, непосредственно предшествующий (возможно, аннотированному) package объявлению в package-info.java. Таким образом, package-info.java становится единственным хранилищем аннотаций и документации на уровне пакета. Если в будущем потребуется добавить другую информацию на уровне пакета, этот файл окажется удобным хранилищем для этой информации.

7.4.2. Пакеты без имени

Единица компиляции, в которой нет объявления пакета, является частью пакета без имени.

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

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

В качестве примера, единица компиляции:

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

определяет очень простую единицу компиляции как часть пакета без имени.

Реализация платформы Java SE должна поддерживать по крайней мере один пакет без имени; она может поддерживать более одного пакета без имени, но это не обязательно. Которые единицы компиляции находятся в каждом пакете без имени, определяется хост-системой.

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

7.4.3. Наблюдаемость пакета

Пакет является наблюдаемым только в том случае, если выполняется одно из следующих условий:

  • Единица компиляции, содержащая объявление пакета, является наблюдаемой (§7.3).

  • Подпакет пакета является наблюдаемым.

Пакеты java, java.lang и java.io всегда наблюдаемы.

Это можно заключить из вышеуказанного правила и правил наблюдаемых единиц компиляции следующим образом. Предварительно определённый пакет java.lang объявляет класс Object, поэтому единица компиляции для Object всегда наблюдаема (§7.3). Следовательно, пакет java.lang наблюдаем (§7.4.3), и пакет java также. Кроме того, поскольку Object наблюдаем, тип массива Object[] неявно существует. Его суперинтерфейс java.io.Serializable (§10.1) также существует, следовательно, пакет java.io наблюдаем.

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

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

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


ОбъявлениеИмпорта:
ОбъявлениеИмпортаОдиночногоТипа
ОбъявлениеИмпортаВсехТипов
ОбъявлениеИмпортаОдиночногоСтатическогоЧлена
ОбъявлениеИмпортаВсехСтатическихЧленов

  • Объявление импорта одиночного типа (§7.5.1) импортирует один именованный тип, указав его каноническое имя (§6.7).

  • Объявление импорта всех типов (§7.5.2) импортирует все доступные (§6.6) типы именованного типа или именованного пакета по мере необходимости, указывая каноническое имя типа или пакета.

  • Объявление импорта одиночного статического члена (§7.5.3) импортирует все доступные static члены с заданным именем из типа, указав его каноническое имя.

  • Объявление импорта всех статических членов (§7.5.4) импортирует все доступные static члены именованного типа по мере необходимости, указывая каноническое имя типа.

Область действия и перекрытие импортируемого типа или члена определены в §6.3 и §6.4.

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

Тип в безымянном пакете (§7.4.2) не имеет канонического имени, поэтому требование канонического имени в каждом виде объявления импорта подразумевает, что (а) типы в безымянном пакете не могут быть импортированы, и (б) static члены типов в безымянном пакете не могут быть импортированы. Таким образом, §7.5.1, §7.5.2, §7.5.3 и §7.5.4 все требуют ошибки компиляции при попытке импортировать тип (или static член) в безымянном пакете.

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

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


ОбъявлениеИмпортаОдиночногоТипа:
import ИмяТипа ;

ИмяТипа должно быть каноническим именем (§6.7) типа класса, типа интерфейса, типа перечисления или типа аннотации.

Ошибка компиляции, если имя типа недоступно (§6.6).

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


import java.util.Vector;

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

Обратите внимание, что java.util.Vector объявлен как обобщенный тип (§8.1.2). После импорта имя Vector может использоваться без квалификации в параметризованном типе, таком как Vector<String>, или как необобщенный тип Vector. Это подчеркивает ограничение объявления import: вложенный тип внутри объявления обобщенного типа может быть импортирован, но его внешний тип всегда стирается.


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

Если тип, импортируемый объявлением импорта одиночного типа, объявлен в единице компиляции, содержащей объявление import, объявление import игнорируется.

Если объявление импорта одиночного типа импортирует тип с простым именем n, а единица компиляции также объявляет тип верхнего уровня (§7.6) с простым именем n, возникает ошибка компиляции.

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

Пример 7.5.1-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; }


Пример 7.5.1-3. Отсутствие импорта подпакета

Обратите внимание, что объявление import не может импортировать подпакет, только тип.

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


import java.util;
class Test { util.Random generator; }
  // incorrect: compile-time error


Пример 7.5.1-4. Импорт имени типа, которое также является именем пакета

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

package Vector;
public class Mosquito { int capacity; }

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

package strange;
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());
    }
}

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

class java.util.Vector
class Vector.Mosquito

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

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


TypeImportOnDemandDeclaration:
import PackageOrTypeName . * ;

Значение PackageOrTypeName должно быть каноническим именем (§6.7) пакета, класса, интерфейса, перечисления или аннотации.

Если указанный пакет или тип недоступен (§6.6), возникает ошибка компиляции.

Использование имени текущего пакета или java.lang в объявлении импорта типов по требованию не является ошибкой компиляции. В таких случаях объявление игнорируется.

Пример 7.5.2-1. Импорт типов по требованию


import java.util.*;

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

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

Объявление может быть скрыто объявлением поля, параметра или локальной переменной с именем Vector.

(Необычно, чтобы любое из этих условий выполнялось.)


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

Если единица компиляции содержит как объявление импорта типов по требованию, так и объявление статического импорта по требованию (§7.5.4), которые называют один и тот же тип, эффект такой же, как если бы члены-типы этого типа (§8.5, §9.5) были импортированы только один раз.

7.5.3. Объявления одиночного статического импорта

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


SingleStaticImportDeclaration:
import static TypeName . Identifier ;

Значение TypeName должно быть каноническим именем (§6.7) класса, интерфейса, перечисления или аннотации.

Если указанный тип недоступен (§6.6), возникает ошибка компиляции.

Значение Identifier должно называть по крайней мере одного static члена указанного типа. Возникает ошибка компиляции, если члена с таким именем нет или если все члены с таким именем недоступны.

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

Если объявление одиночного статического импорта импортирует тип, простое имя которого n, и единица компиляции также объявляет тип верхнего уровня (§7.6) с простым именем n, возникает ошибка компиляции.

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

7.5.4. Объявления статического импорта по требованию

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


StaticImportOnDemandDeclaration:
import static TypeName . * ;

Значение TypeName должно быть каноническим именем (§6.7) класса, интерфейса, перечисления или аннотации.

Если указанный тип недоступен (§6.6), возникает ошибка компиляции.

В одной единице компиляции может быть два или более объявлений статического импорта по требованию, которые называют один и тот же тип; эффект такой же, как если бы было ровно одно такое объявление.

В одной единице компиляции может быть два или более объявлений статического импорта по требованию, которые называют один и тот же член; эффект такой же, как если бы член был импортирован ровно один раз.

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

Если единица компиляции содержит как объявление статического импорта по требованию, так и объявление импорта типа по требованию (§7.5.2), которые называют один и тот же тип, эффект такой же, как если бы члены-типы этого типа (§8.5, §9.5) были импортированы только один раз.

7.6. Объявления типов верхнего уровня

Объявление типа верхнего уровня объявляет тип класса верхнего уровня (§8) или тип интерфейса верхнего уровня (§9).


ОбъявлениеТипа:
ОбъявлениеКласса
ОбъявлениеИнтерфейса
;

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

Ошибка компиляции, если объявление типа верхнего уровня содержит какой-либо из следующих модификаторов доступа: protected, private или static.

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

Ошибка компиляции, если имя типа верхнего уровня также объявлено как тип с помощью объявления импорта одного типа (§7.5.1) в единице компиляции, содержащей объявление типа.

Пример 7.6-1. Конфликтующие объявления типов верхнего уровня

package test;
import java.util.Vector;
class Point {
    int x, y;
}
interface Point {  // compile-time error #1
    int getR();
    int getTheta();
}
class Vector { Point[] pts; }  // compile-time error #2

Здесь первая ошибка компиляции вызвана дублированием объявления имени Point как класса, так и интерфейса в одном пакете. Вторая ошибка компиляции — попытка объявить имя Vector как типом объявления класса, так и с помощью объявления импорта одного типа.

Однако, не является ошибкой, если имя класса также является именем типа, который в противном случае мог бы быть импортирован объявлением импорта типа по требованию (§7.5.2) в единице компиляции (§7.3), содержащей объявление класса. Таким образом, в этой программе:

package test;
import java.util.*;
class Vector {}  // not a compile-time error

объявление класса Vector разрешено, даже если также есть класс java.util.Vector. Внутри этой единицы компиляции простое имя Vector относится к классу test.Vector, а не к java.util.Vector (к которому всё ещё можно обратиться из кода в единице компиляции, но только по его полному имени).


Пример 7.6-2. Область действия типов верхнего уровня

package points;
class Point {
    int x, y;           // coordinates
    PointColor color;   // color of this point
    Point next;         // next point with this color
    static int nPoints;
}
class PointColor {
    Point first;        // first point with this color
    PointColor(int color) { this.color = color; }
    private int color;  // color components
}

Эта программа определяет два класса, которые используют друг друга в объявлениях своих членов класса. Поскольку типы классов Point и PointColor имеют в своей области действия все объявления типов в пакете points, включая все в текущей единице компиляции, эта программа компилируется без ошибок. То есть, ссылка вперёд не является проблемой.


Область действия и перекрытие типа верхнего уровня указаны в §6.3 и §6.4.

Полное имя типа верхнего уровня указано в §6.7.

Пример 7.6-3. Полные имена


class Point { int x, y; }

В этом коде класс Point объявлен в единице компиляции без оператора package, и поэтому Point является его полным именем, в то время как в коде:


package vista;
class Point { int x, y; }

полное имя класса Point является vista.Point. (Имя пакета vista подходит для локального или личного использования; если пакет предназначен для широкого распространения, лучше присвоить ему уникальное имя пакета (§6.1).)


Реализация платформы Java SE должна отслеживать типы в пакетах по их двоичным именам (§13.1). Несколько способов именования типа должны быть преобразованы в двоичные имена, чтобы убедиться, что такие имена понимаются как ссылки на тот же тип.

Например, если единица компиляции содержит объявление импорта одного типа (§7.5.1):


import java.util.Vector;

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

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

  • К типу обращается код в других единицах компиляции пакета, в котором тип объявлен.

  • Тип объявлен как public (и, следовательно, потенциально доступен из кода в других пакетах).

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

Например, исходный код типа public wet.sprocket.Toad будет найден в файле Toad.java в директории wet/sprocket, а соответствующий объектный код — в файле Toad.class в той же директории.

© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API