W3docs

Оператор 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.langString, 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 — явный импорт одного типа имеет приоритет над импортом по требованию, поэтому такой случай компилируется без ошибок. Ошибкой является только наличие двух импортов одного типа для одного и того же простого имени.

Это та же проблема, которую глава о пакетах рассматривала с точки зрения пакетов.

Практический пример

Эта программа использует импорт во всех трёх формах — одиночный, по маске, статический — и затем во время выполнения проверяет, что полученные классы именно из тех пакетов.

java— editable, runs on the server

Первые три импорта охватывают все формы, которые есть в языке. Обратите внимание, что маска import java.util.*; делает доступными List, Collections и Date — явный import java.util.ArrayList; в этом файле избыточен, но именно такую строку может требовать руководство по стилю проекта для читаемости.

Что дальше

Вы увидели, как извлекать типы из пакетов. Следующий шаг — другая сторона медали: объявление собственного пакета и размещение файлов так, чтобы компилятор и JVM были довольны. Переходите к созданию пользовательских пакетов в Java.

Практика

Практика
Что на самом деле вводит в область видимости `import java.util.*;`?
Что на самом деле вводит в область видимости `import java.util.*;`?
Was this page helpful?