Почему использование подстановочного знака в операторе импорта Java считается плохой практикой?
На StackOverflow.com:
Я сталкиваюсь с проблемой выбора между использованием регулярного импорта отдельных классов в Java и использованием wildcard импорта. Я понимаю, что такой способ, как:
import java.awt.*;
работает гораздо удобнее и эстетичнее, чем перечисление всех классов по отдельности:
import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Canvas;
...
Однако, меня интересует, в чем же заключается проблема использования wildcard в операторе import
? Какие потенциальные недостатки или риски могут возникнуть при таком подходе?
5 ответ(ов)
Единственная проблема с использованием wildcard-импортов (импорт with .*
) заключается в том, что они загромождают ваше локальное пространство имен. Например, предположим, что вы пишете приложение на Swing и вам нужен класс java.awt.Event
, а также вы взаимодействуете с корпоративной системой календаря, которая содержит com.mycompany.calendar.Event
. Если вы импортируете оба класса с помощью wildcard, может произойти одно из трех:
- У вас возникает прямой конфликт имен между
java.awt.Event
иcom.mycompany.calendar.Event
, и вы не сможете даже скомпилировать код. - Вы в итоге импортируете только один (только один из ваших импортов использует
.*
), но это оказывается неправильный класс, и вы пытаетесь выяснить, почему ваш код утверждает, что тип неверный. - Когда вы компилируете свой код, класса
com.mycompany.calendar.Event
нет, но когда его позже добавляют, ваш ранее валидный код вдруг перестает компилироваться.
Преимущество явного перечисления всех импортов заключается в том, что вы можете в одно мгновение определить, какой класс вы имели в виду, что значительно упрощает чтение кода. Если вы просто делаете что-то одноразовое, с точки зрения компилятора ничего явно неправильно, но будущие поддерживающие разработчики будут благодарны вам за ясность в вашем коде.
Вот голос за импорт с помощью звездочки. Оператор импорта предназначен для импорта пакетов, а не отдельных классов. Гораздо удобнее импортировать целые пакеты; проблемы, упомянутые здесь (например, java.sql.Date
и java.util.Date
), можно легко решить другими способами, а не конкретными импортами, и они определенно не оправдывают создания запутанных импортов для каждого класса. Ничто так не раздражает, как открытие исходного файла и необходимость просматривать 100 операторов импорта.
Использование конкретных импортов усложняет рефакторинг; если вы удаляете или переименовываете класс, вам нужно удалить все его конкретные импорты. Если вы переключаете реализацию на другой класс в том же пакете, вам нужно исправить импорты. Хотя эти дополнительные шаги можно автоматизировать, они создают реальные потери продуктивности без ощутимых преимуществ.
Если бы Eclipse по умолчанию не использовал конкретные импорты классов, все бы по-прежнему использовали импорты со звездочкой. Извините, но действительно нет рационального оправдания для использования конкретных импортов.
Вот как справиться с конфликтами классов:
import java.sql.*;
import java.util.*;
import java.sql.Date;
Производительность: Нет влияния на производительность, так как байт-код остается тем же. Однако это приведет к некоторым накладным расходам при компиляции.
Компиляция: На моем персональном компьютере компиляция пустого класса без импортов занимает 100 мс, в то время как тот же класс с импортом java.* занимает 170 мс.
Использование wildcard импорта, такого как import java.util.*;
и import java.awt.*;
, загромождает ваше пространство имен, что требует явного указания имен классов в случае неоднозначности. Наиболее распространенный случай может возникнуть, когда вы пишете:
List blah; // Неоднозначно, требует уточнения.
Кроме того, явные импорты помогают сделать ваши зависимости более явными, так как все они перечислены в начале файла. Это облегчает понимание кода и позволяет избежать потенциальных конфликтов имен.
- Является полезным для выявления конфликтов имен классов: две класса в разных пакетов могут иметь одинаковое имя. Это может быть скрыто с помощью * импорта.
- Делает зависимости явными, так что любой, кто будет читать ваш код позже, увидит, что вы намеревались импортировать, а что нет.
- Может ускорить компиляцию, поскольку компилятору не нужно искать по всему пакету для выявления зависимостей, хотя с современными компиляторами это обычно не является серьезной проблемой.
- Неудобства явных импортов минимизированы в современных IDE. Большинство IDE позволяют свернуть раздел импортов, чтобы он не мешал, автоматически добавляют импорты по необходимости и автоматически выявляют неиспользуемые импорты, чтобы помочь с их удалением.
В большинстве мест, где я работал и использовался значительный объем Java, явные импорты стали частью стандарта кодирования. Иногда я все еще использую * для быстрого прототипирования, а затем расширяю списки импортов (некоторые IDE могут сделать это за вас), когда дело доходит до коммерциализации кода.
Изменение имени импорта в Java или импорт двух классов с одинаковым именем
Почему нет ConcurrentHashSet, если есть ConcurrentHashMap?
Как объявить массив в одну строку?
Загрузка JDK Java на Linux через wget приводит к отображению страницы лицензии вместо установки
Создание репозитория Spring без сущности