Оператор import в Java
Подключайте типы в Java с помощью import, импорта по маске и статического импорта.
Когда ваш код находится в пакете, любой код вне этого пакета должен обращаться к вашим типам либо по полностью квалифицированному имени (com.w3docs.parser.Tokenizer), либо импортируя их — тогда достаточно короткого имени. Импорт ничего не загружает, ничего не копирует и не влияет на выполнение программы — это чисто компиляционное удобство, которое говорит компилятору, что означает Tokenizer в данном файле. Трёх форм хватит для любой ситуации: импорт одного типа, импорт по требованию (по маске) и статический импорт.
Где размещать импорты
Каждый исходный файл Java следует одному фиксированному порядку:
package com.w3docs.parser; // optional: at most one
import java.util.List; // zero or more imports
import java.util.Map;
public class Tokenizer { /* ... */ }Сначала package (если есть), затем importы, затем объявления типов. Любой другой порядок приводит к ошибке компиляции.
Импорт одного типа
Наиболее распространённая форма — указать один класс:
import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>();После импорта каждое неквалифицированное упоминание ArrayList в файле разрешается в java.util.ArrayList. При необходимости в том же файле можно по-прежнему писать полное имя, чтобы отличить его от другого ArrayList из другого источника.
Импорт по требованию (по маске)
Чтобы подключить всё из пакета, используйте *:
import java.util.*;
List<String> names = new ArrayList<>();
Map<String, Integer> counts = new HashMap<>();Маска импортирует каждый публичный класс верхнего уровня из java.util — но не подпакеты. import java.util.*; не даёт доступа ни к чему из java.util.concurrent; для этого нужен отдельный import java.util.concurrent.*;. Не существует и краткой формы import java.*; — пакет java не содержит классов, только подпакеты.
Распространённый стилистический спор: импорт одного типа делает зависимости файла явными и читаемыми; маска сокращает блок импортов. IDE одинаково хорошо обрабатывают оба варианта, поэтому выбор — в основном вопрос стиля проекта. Google Java Style Guide запрещает маски; многие проекты с открытым исходным кодом их допускают. Выберите один подход и придерживайтесь его.
Статический импорт
Статический импорт вводит в область видимости static-член — метод или поле — чтобы обращаться к нему без указания класса:
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
double hypotenuse(double a, double b) {
return sqrt(a * a + b * b); // not Math.sqrt
}Статический импорт особенно удобен в тестовом коде — assertEquals(...) читается лучше, чем Assertions.assertEquals(...), — и в формулах с интенсивными вычислениями, где имя класса — просто шум. Проблемы возникают при злоупотреблении: читатель файла вынужден разыскивать импорты, чтобы понять, откуда берётся голое assertThat(...). Используйте статический импорт тогда, когда имена функций хорошо известны и однозначны в данном контексте.
Маска работает и для статического импорта: import static java.lang.Math.*; подключает все публичные статические члены Math. Те же оговорки о ясности кода применимы и здесь.
Что импортируется автоматически
Java автоматически импортирует ряд вещей, и их никогда не нужно писать явно:
- Каждый класс из
java.lang—String,Object,Math,Integer,Thread,Throwableи остальные. - Каждый класс из вашего собственного пакета.
Именно поэтому вы можете использовать String и System.out.println без строки import. Всё остальное нужно подключать явно.
Разрешение конфликтов имён
Два импорта с одинаковым простым именем не компилируются — java.util.Date и java.sql.Date не могут быть одновременно импортированы в один файл. Решение — импортировать один и квалифицировать другой:
import java.util.Date; // imported short
// Use java.sql.Date by its full name where it appears:
java.sql.Date dbDate = resultSet.getDate(1);
Date now = new Date();Импорт одного типа всегда имеет приоритет над маской. Если одновременно присутствуют import java.util.*; и import java.sql.Date;, голое Date означает java.sql.Date — явный импорт одного типа имеет приоритет над импортом по требованию, поэтому такой случай компилируется без ошибок. Ошибкой является только наличие двух импортов одного типа для одного и того же простого имени.
Это та же проблема, которую глава о пакетах рассматривала с точки зрения пакетов.
Практический пример
Эта программа использует импорт во всех трёх формах — одиночный, по маске, статический — и затем во время выполнения проверяет, что полученные классы именно из тех пакетов.
Первые три импорта охватывают все формы, которые есть в языке. Обратите внимание, что маска import java.util.*; делает доступными List, Collections и Date — явный import java.util.ArrayList; в этом файле избыточен, но именно такую строку может требовать руководство по стилю проекта для читаемости.
Что дальше
Вы увидели, как извлекать типы из пакетов. Следующий шаг — другая сторона медали: объявление собственного пакета и размещение файлов так, чтобы компилятор и JVM были довольны. Переходите к созданию пользовательских пакетов в Java.