Если вспомнить, что пакеты предлагают эффективный механизм изоляции различных классов друг от друга, то становится понятно, почему все встроенные классы Java хранятся в пакетах.
Ни один из основных классов Java не хранится в неименованном пакете, используемом по умолчанию. Все стандартные классы непременно хранятся в каком-нибудь именованном пакете.
А поскольку в самих пакетах классы должны полностью определяться по именам их пакетов, то длинное, разделяемое точками имя пути к пакету каждого используемого класса может оказаться слишком громоздким.
Следовательно, чтобы отдельные классы или весь пакет можно было сделать доступными, в Java внедрен оператор import.
После того как класс импортирован, на него можно ссылаться непосредственно, используя только его имя.
Оператор import служит только для удобства программирования и не является обязательным с формальной точки зрения для создания завершенной программы нa java.
Но если в прикладном коде приходится ссылаться на несколько десятков классов, то оператор import значительно сокращает объем вводимого исходного кода.
В исходном файле программы нa java операторы import должны следовать непосредственно за оператором package (если таковой имеется) и перед любыми определениями классов.
Оператор import имеет следующую общую форму:
1 |
import пакет1 [.пакет2].(имя_класса | *); |
где пакет1 обозначает имя пакета верхнего уровня, а пакет 2 — имя подчиненного пакета из внешнего пакета, отделяемое знаком точки (.).
Глубина вложенности пакетов практически не ограничивается ничем, кроме файловой системы.
И наконец, имя_класса может быть задано явно или с помощью знака «звездочка» (*) который указывает компилятору Java на необходимость импорта всего пакета.
В следующем фрагменте кода демонстрируется применение обоих вариантов общей формы оператора import:
1 2 |
import java.util.Date; import java.io.*; |
Все классы из стандартной библиотеки Java хранятся в пакете java. Основные языковые средства хранятся в пакете java.lang, входящем в пакет java.
Обычно каждый пакет или класс, который требуется использовать, приходится импортировать. Но поскольку программировать на Java бесполезно без многих средств, определенных в пакете java.lang, компилятор неявно импортирует его для всех программ.
Это равнозначно наличию следующей строки кода в каждой из программ на Java:
1 |
import java.lang.*; |
Компилятор никак не отреагирует на наличие классов с одинаковыми именами в двух разных пакетах, импортируемых в форме со звездочкой, если только не будет предпринята попытка воспользоваться одним из этих классов.
В таком случае возникнет ошибка во время компиляции, и тогда имя класса придется указать явно вместе с его пакетом.
Следует особо подчеркнуть, что указывать оператор import совсем не обязательно.
Полностью уточненное имя класса с указанием всей иерархии пакетов можно использовать везде, где допускается имя класса.
Например, в приведенном ниже фрагменте кода применяется оператор import.
1 2 3 4 5 |
import java.util.*; class MyDate extends Date { } |
Этот же фрагмент кода, но без оператора import, показан ниже. В этой версии класс Date полностью определен.
1 2 3 |
class MyDate extends java.util.Date { } |
Запомните, что при импорте пакета классам, не производным от классов из данного пакета в импортирующем коде, будут доступны только те элементы пакета, которые объявлены как public.
Так, если требуется, чтобы класс Balance из пакета MyPack был доступен в качестве самостоятельного класса за пределами пакета MyPack, его следует объявить как public и разместить в отдельном файле, как показано в приведенном ниже примере кода.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package MyPack; /* Теперь класс 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.println("--> "); System.out.println(name + ": $" + bal); } } } |
Как видите, класс Balance теперь объявлен как public. Его конструктор и метод show() также объявлены как public.
Это означает, что они доступны для любого кода за пределами пакета MyPack. Например, класс TestBalance импортирует пакет MyPack, и поэтому в нем может быть использован класс Balance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import MyPack.*; class TestBalance { public static void main(String args[]) { /* Класс Balance объявлен как public, поэтому им можно воспользоваться и вызвать его конструктор. */ Balance test = new Balance("Michael M. A.", 133.23); test.show(); // можно также вызвать метод show(); } } |
В качестве эксперимента удалите модификатор public из объявления класса Balance, а затем попытайтесь скомпилировать класс TestBalance. Как упоминалось выше, это приведет к появлению ошибок.