Импорт пакетов

Если вспомнить, что пакеты предлагают эффективный механизм изоляции различных классов друг от друга, становится понятно, почему все встроенные классы Java хранятся в пакетах. Ни один из основных классов Java не хранится в неименованном пакете, используемом по умолчанию. Все стандартные классы хранятся в каком-либо именованном пакете. Поскольку внутри пакетов классы должны быть полностью определены именем или именами их пакетов, длинное, разделенное точками имя пути пакета каждого используемого класса может оказаться слишком громоздким. Поэтому, чтобы определенные классы или весь пакет можно было сделать видимыми, в Java включен оператор import. После того как класс импортирован, на него можно ссылаться непосредственно, используя только его имя. Оператор import служит только для удобства программистов и не является обязательным с технической точки зрения для создания завершенной Java-программы. Однако если в приложении придется ссылаться на несколько десятков классов, оператор import значительно уменьшит объем вводимого кода.

В исходном файле Java-программы операторы import должны следовать непосредственно за оператором package (если таковой имеется) перед любыми определениями классов. Оператор import имеет следующую общую форму:

import пакет1 [.пакет2].(имя__класса|*);

В этой форме пакет! — имя пакета верхнего уровня, па кет 2 — имя подчиненного пакета внутри внешнего пакета, отделенное символом точки (.). Глубина вложенности пакетов практически не ограничена ничем, кроме файловой системы. И, наконец, имя_ класса может быть задано либо явно, либо с помощью символа звездочки (*), который указывает компилятору Java о необходимости импорта всего пакета. Следующий фрагмент демонстрирует применение обеих форм оператора:

import java.util.Date;
import java.io.*;

Внимание! Использование формы с применением символа звездочки может привести к увеличению времени компиляции — особенно при импорте нескольких больших пакетов. Поэтому советуем явно указывать имена классов, которые нужно использовать, а не импортировать пакеты полностью. Однако использование формы с применением звездочки никак не влияет на производительность системы времени выполнения или на размеры классов.

Все стандартные классы, поставляемые с системой Java, хранятся в пакете j ava. Основные функции языка хранятся в пакете j ava. lang внутри пакета j ava. Обычно каждый пакет или класс, который нужно использовать, приходится импортировать. Но поскольку система Java бесполезна без многих функций, определенных в пакете java. lang, компилятор неявно импортирует его для всех программ. Это эквивалентно присутствию следующей строки в каждой из программ:

import java.lang.*;

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

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

import java.util.*;
class MyDate extends Date {
}

Этот же пример без оператора import выглядит следующим образом:

class MyDate extends java.util.Date { }

В этой версии объект Date полностью определен.

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

/* Теперь класс Balance, его конструктор и его метод show ()
являются общедоступными. Это означает, что вне их пакета они могут
использоваться кодом, не являющимся подклассом пакета. */
public class Balance {
String name;
double bal;
public Balance(String n, double b) {
name = n;
bal = b;
}
public void show() {
if(bal<0)
System.out.print("--> ");
System.out.println(name + ": $" + bal);
}
}

Как видите, теперь класс Balance объявлен как public. Его конструктор и метод show () также объявлены как public. Это означает, что они доступны любому коду вне пакета МуРаск. Например, класс TestBalance импортирует пакет МуРаск и поэтому может использовать класс Balance:

import МуРаск.*;
class TestBalance {
public static void main(String args[]) {
/* Поскольку класс Balance объявлен как public, его можно
использовать и вызывать его конструктор. */
Balance test = new Balance ("J. J. Jaspers", 99.88);
test.show(); // можно также вызывать метод show()
}
}

В качестве эксперимента удалите спецификатор public из класса Balance, а затем попытайтесь выполнить компиляцию класса TestBalance. Как уже было сказано, это приведет к возникновению ошибок.