Статический импорт

В J2SE 5 появилось новое средство Java — статический импорт, что расширяет возможности ключевого слова import, import с предшествующим ключевым словом static может применяться для импорта статических членов класса или интерфейса. При использовании статического импорта появляется возможность ссылаться на статические члены непосредственно по именам, без необходимости квалифицировать их именем класса. Это упрощает и сокращает синтаксис, необходимый для работы со статическими членами.

Чтобы понять удобство статического импорта, давайте начнем с примера, который не использует его. Следующая программа вычисляет гипотенузу прямоугольного треугольника. Она использует два статических метода из встроенного Java-класса Math, входящего в пакет java.lang. Первый из них — Math.pow() — возвращает значение, возведенное в указанную степень. Второй — Math.sqrt () — возвращает квадратный корень аргумента.

// Вычисляет длину гипотенузы прямоугольного треугольника.
class Hypot {
public static void main(String args[]) {
double sidel, side2;
double hypot;
sidel = 3.0;
side2 =4.0;
// Обратите внимание, что sqrt() и pow() должны быть
// квалифицированы именем их класса - Math.
hypot = Math.sqrt(Math.pow(sidel, 2) + Math.pow(side2, 2));
System.out.println("Даны длины сторон " + sidel + " и " + side2 + " гипотенуза равна " + hypot) ;
}
}

Поскольку pow () и sqrt () — статические методы, они должны быть вызваны с указанием имени их класса — Math. Это приводит к следующему громоздкому вычислению гипотенузы:

hypot = Math.sqrt(Math.pow(sidel, 2) + Math.pow(side2, 2));

Как иллюстрирует этот простой пример, необходимость каждый раз специфицировать имя класса при вызовах pow () и sqrt () (или любых других математических методов Java вроде sin (), cos () и tan ()) довольно утомительно.

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

// Применение статического импорта, делающего sqrt() и pow () видимыми.
import static Java.lang.Math.sqrt;
import static Java.lang.Math.pow;
// Вычисление гипотенузы прямоугольного треугольника.
class Hypot {
public static void main(String args[]) {
double sidel, side2;
double hypot;
sidel = 3.0;
side2 = 4.0;
// Здесь sqrt() npow() можно вызывать
// непосредственно, без их имени класса.
hypot = sqrt(pow(sidel, 2) + pow(side2, 2));
System.out.println("Даны длины сторон " + sidel + " и " + side2 + " гипотенуза равна " + hypot) ;
}
}

В этой версии имена sqrt и pow становятся видимыми благодаря оператору статического импорта:

import static java.lang.Math.sqrt;
import static java.lang.Math.pow;

После этих операторов больше нет необходимости квалифицировать pow () и sqrt () именем их класса. Таким образом, вычисление гипотенузы может быть выражено более удобно:

hypot = sqrt(pow(sidel, 2) + pow(side2, 2));

Как видите, эта форма и более читабельна.

Существуют две основных формы оператора import static. Первая, которая использовалась в предыдущем примере, делает видимым единственное имя. Его общая форма такова:

import static pkg.type-name.static-member-name;

Здесь type-name — имя класса или интерфейса, который содержит требуемый статический член. Полное имя его пакета указано в ркд, а имя члена — в static-member-name.

Вторая форма статического импорта позволяет импортировать все статические члены данного класса или интерфейса. Его общая форма показана ниже.

import static pkg.type-name.*;

Если вы будете использовать много статических методов или полей, определенных в классе, то эта форма позволит вам сделать их видимыми без необходимости специфицировать каждый отдельно. Таким образом, в предыдущей программе с помощью единственного оператора import можно ввести в область видимости pow () и sqrt () (а также все другие статические члены Math):

import static java.lang.Math.*;

Конечно же, статический импорт не ограничивается только классом Math или его методами. Например, следующая строка вводит в область видимости статическое поле System.out:

import static java.lang.System.out;

После этого оператора вы можете выводить информацию на консоль потоком out, не квалифицируя его System, как показано здесь:

out.println("Импортировав System.out, вы можете использовать его непосредственно.");

Однако импортировать System, out, как показано выше — это не только хорошая идея, но и предмет обсуждения. Несмотря на то что это сокращает текст программы, все же теперь не будет очевидно тем, кто читает программу, что out ссылается на System.out.

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

Каким бы удобным ни показался статический импорт, важно не злоупотреблять им. Помните, что причина того, что библиотечные классы Java объединены в пакеты, состоит в том, чтобы избежать конфликтов пространств имен и для непреднамеренного сокрытия прочих имен. Если вы используете в своей программе статический член однажды или дважды, лучше его не импортировать. К тому же некоторые статические имена, как, например System.out, настолько привычны и узнаваемы, что, вероятно, вы вообще не захотите импортировать их.

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