Эккель Брюс
Шрифт:
Размещение файлов пакета в отдельном каталоге решает две другие задачи: создание уникальных имен пакетов и обнаружение классов, потерянных в «дебрях» структуры каталогов. Как было упомянуто в главе 2, проблема решается «кодированием» пути файла в имени пакета. По общепринятой схеме первая часть имени пакета должна состоять из перевернутого доменного имени разработчика класса. Так как доменные имена Интернета уникальны, соблюдение этого правила обеспечит уникальность имен пакетов и предотвратит конфликты. (Только если ваше доменное имя не достанется кому-то другому, кто начнет писать программы на Java под тем же именем.) Конечно, если у вас нет собственного доменного имени, для создания уникальных имен пакетов придется придумать комбинацию с малой вероятностью повторения (скажем, имя и фамилия). Если же вы решите публиковать свои программы на Java, стоит немного потратиться на получение собственного доменного имени.
Вторая составляющая — преобразование имени пакета в каталог на диске компьютера. Если программе во время исполнения понадобится загрузить файл .class (что делается динамически, в точке, где программа создает объект определенного класса, или при запросе доступа к статическим членам класса), она может найти каталог, в котором располагается файл .class.
Интерпретатор Java действует по следующей схеме. Сначала он проверяет переменную окружения CLASSPATH (ее значение задается операционной системой, а иногда программой установки Java или инструментарием Java). CLASSPATH содержит список из одного или нескольких каталогов, используемых в качестве корневых при поиске файлов .class. Начиная с этих корневых каталогов, интерпретатор берет имя пакета и заменяет точки на слеши для получения полного пути (таким образом, директива package foo.bar.baz преобразуется в foo\bar\baz, foo/bar/baz или что-то еще в зависимости от вашей операционной системы). Затем полученное имя присоединяется к различным элементам CLASSPATH. В указанных местах ведется поиск файлов .class, имена которых совпадают с именем создаваемого программой класса. (Поиск также ведется в стандартных каталогах, определяемых местонахождением интерпретатора Java.)
Чтобы понять все сказанное, рассмотрим мое доменное имя: MindView.net. Обращая его, получаем уникальное глобальное имя для моих классов: net. mindview. (Расширения com, edu, org и другие в пакетах Java прежде записывались в верхнем регистре, но начиная с версии Java 2 имена пакетов записываются только строчными буквами.) Если потребуется создать библиотеку с именем simple, я получаю следующее имя пакета:
package net.mindview.simple,
Теперь полученное имя пакета можно использовать в качестве объединяющего пространства имен для следующих двух файлов:
//: net/mindview/simple/Vector.java
// Создание пакета
package net mindview simple,
public class Vector { public VectorО {
System out printlnCnet mindview.simple.Vector");
}
} ///:-
Как упоминалось ранее, директива package должна находиться в первой строке исходного кода. Второй файл выглядит почти так же:
//: net/mindview/simple/List java
// Создание пакета
package net.mindview simple;
public class List { public ListO {
System.out pri ntln("net.mi ndvi ew.si mple.Li st"),
}
} /// ~
В моей системе оба файла находятся в следующем подкаталоге:
С \DOC\JavaT\net\mindview\simple
Если вы посмотрите на файлы, то увидите имя пакета net.mindview.simple, но что с первой частью пути? О ней позаботится переменная окружения CLAS-SPATH, которая на моей машине выглядит следующим образом:
CLASSPATH= ,D \JAVA\LIB,C.\D0C\JavaT
Как видите, CLASSPATH может содержать несколько альтернативных путей для поиска.
Однако для файлов JAR используется другой подход. Вы должны записать имя файла JAR в переменной CLASSPATH, не ограничиваясь указанием пути к месту его расположения. Таким образом, для файла JAR с именем grape.jar переменная окружения должна выглядеть так:
CLASSPATH= .D.\JAVAXLIB.С \flavors\grape.jar
После настройки CLASSPATH следующий файл можно разместить в любом каталоге:
// access/LibTest.java // Uses the library, import net mindview simple *;
public class LibTest {
public static void main(String[] args) { Vector v = new VectorO. List 1 = new ListO:
}
} /* Output:
net.mindview simple Vector net mindview.simple List */// -
Когда компилятор встречает директиву import для библиотеки simple, он начинает поиск в каталогах, перечисленных в переменной CLASSPATH, найдет каталог net/mindview/simple, а затем переходит к поиску компилированных файлов с подходящими именами (Vector.class для класса Vector и List.class для класса List). Заметьте, что как классы, так и необходимые методы классов Vector и List должны быть объявлены со спецификатором public.
Конфликты имен
Что происходит при импортировании конструкцией * двух библиотек, имеющих в своем составе идентичные имена? Предположим, программа содержит следующие директивы:
import net mindview simple *; import java.util.*,
Так как пакет java,util.* тоже содержит класс с именем Vector, это может привести к потенциальному конфликту. Но, пока вы не начнете писать код, вызывающий конфликты, все будет в порядке — и это хорошо, поскольку иначе вам пришлось бы тратить лишние усилия на предотвращение конфликтов, которых на самом деле нет.