Почему использование группового символа с оператором импорта Java плохо?

Гораздо удобнее и чище использовать один оператор вроде

import java.awt.*;

чем импортировать кучу отдельных классов

import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Canvas;
...

Что не так с использованием шаблона в выражении import?

Ответ 1

Единственная проблема заключается в том, что он загромождает ваше местное пространство имен. Например, скажем, что вы пишете приложение Swing, поэтому нам нужно java.awt.Event, а также взаимодействовать с системой календаря компании, которая имеет com.mycompany.calendar.Event. Если вы импортируете оба метода с использованием подстановочного знака, произойдет одно из следующих трех действий:

  • У вас есть прямой конфликт имен между java.awt.Event и com.mycompany.calendar.Event, поэтому вы даже не можете скомпилировать.
  • Фактически вам удаётся только импортировать один (только один из ваших двух импортирует .*), но он неправильный, и вы пытаетесь понять, почему ваш код утверждает, что тип неверен.
  • Когда вы компилируете свой код, нет com.mycompany.calendar.Event, но когда они потом добавляют один, ваш предыдущий действительный код внезапно прекращает компиляцию.

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

Ответ 2

Здесь голосуют за импорт звезд. Оператор импорта предназначен для импорта пакета, а не класса. Гораздо чище импортировать целые пакеты; выявленные здесь проблемы (например, java.sql.Date vs java.util.Date) легко устраняются другими средствами, которые на самом деле не решаются с помощью конкретного импорта, и, конечно, не оправдывают безумно педантичный импорт для всех классов. Нет ничего более смущающего, чем открытие исходного файла и необходимость пролистать 100 операторов импорта.

Выполнение определенного импорта затрудняет рефакторинг; если вы удаляете/переименовываете класс, вам нужно удалить все его специфические импорты. Если вы переключаете реализацию на другой класс в том же пакете, вы должны исправить импорт. Несмотря на то, что эти дополнительные шаги могут быть автоматизированы, они действительно наносят удар по производительности без реальной выгоды.

Даже если Eclipse не выполняет импорт классов по умолчанию, все равно будут выполнять импорт звездочек. Извините, но на самом деле нет рационального обоснования для выполнения конкретного импорта.

Вот как бороться с конфликтами классов:

import java.sql.*;
import java.util.*;
import java.sql.Date;

Ответ 3

см. мою статью Импорт по требованию зла

Короче говоря, самая большая проблема заключается в том, что ваш код может сломаться, когда класс добавляется в импортируемый вами пакет. Например:

import java.awt.*;
import java.util.*;

// ...

List list;

В Java 1.1 это было хорошо; Список был найден в java.awt, и конфликта не было.

Теперь предположим, что вы проверяете свой отлично действующий код, а через год кто-то другой его выдает, чтобы редактировать его, и использует Java 1.2.

Java 1.2 добавила интерфейс с именем List to java.util. БУМ! Конфликт. Совершенно рабочий код больше не работает.

Это функция языка EVIL. Нет никакой причины, что код должен прекращать компиляцию только потому, что тип добавлен в пакет...

Кроме того, это затрудняет для читателя определить, какой "Foo" вы используете.

Ответ 4

Неплохо использовать подстановочный знак с оператором импорта Java.

В Чистом коде Роберт С. Мартин фактически рекомендует использовать их, чтобы избежать длинных списков импорта.

Вот рекомендация:

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

Если вы используете два или более классов из пакета, то импортируйте весь пакет с

импортная упаковка. *;

Длинные списки импорта пугают читателя. Мы не хотим загромождать вершины наших модулей с 80 линиями импорта. Скорее мы хотим, чтобы импорт был кратким выражением о том, с какими пакетами мы сотрудничаем.

Конкретный импорт - это жесткие зависимости, тогда как импорт с использованием подстановочных знаков - нет. Если вы специально импортируете класс, то этот класс должен существовать. Но если вы импортируете пакет с подстановочным знаком, никаких особых классов не должно быть. Оператор импорта просто добавляет пакет в путь поиска при поиске имен. Таким образом, при таком импорте не создается никакой реальной зависимости, и поэтому они служат для того, чтобы наши модули были менее связанными.

Есть моменты, когда длинный список конкретных импортов может быть полезен. Например, если вы имеете дело с унаследованным кодом и хотите выяснить, для каких классов вам нужно создавать макеты и заглушки, вы можете пройти по списку определенных импортов, чтобы найти истинные квалифицированные имена всех этих классов, а затем поставить соответствующие заглушки на месте. Тем не менее, это использование для конкретного импорта очень редко. Кроме того, большинство современных IDE позволяют вам конвертировать импортируемые символы в список определенных импортов с помощью одной команды. Так что даже в устаревшем случае лучше импортировать подстановочные знаки.

Импорт подстановочных знаков может иногда вызывать конфликты имен и неоднозначности. Два класса с одинаковыми именами, но в разных пакетах, должны быть специально импортированы или, по крайней мере, специально квалифицированы при использовании. Это может быть неприятно, но достаточно редко, когда использование групповых импортов все же обычно лучше, чем специфический импорт.

Ответ 5

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

import java.util.*;
import java.awt.*;

...
List blah; // Ambiguous, needs to be qualified.

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

Ответ 6

Производительность: влияние на производительность не влияет на байт-код. хотя это приведет к некоторым компиляционным накладным расходам.

Компиляция: на моей персональной машине компиляция пустого класса без импорта ничего занимает 100 мс, но тот же класс при импорте java. * занимает 170 мс.

Ответ 7

  • Он помогает идентифицировать конфликты имен классов: два класса в разных пакетах с одинаковым именем. Это может быть замаскировано с помощью * import.
  • Это делает зависимости явными, так что каждый, кто должен прочитать ваш код, позже знает, что вы хотите импортировать, и то, что вы не хотели импортировать.
  • Это может сделать некоторую компиляцию быстрее, потому что компилятору не нужно искать весь пакет, чтобы идентифицировать depdencies, хотя обычно это не очень важно для современных компиляторов.
  • Неудобные аспекты явного импорта сводятся к минимуму с помощью современных IDE. Большинство IDE разрешают вам свернуть раздел импорта, чтобы он не мешал, автоматически заполнял импорт при необходимости и автоматически определял неиспользуемые импорты, чтобы помочь их очистить.

В большинстве мест, в которых я работал, используя любое значительное количество Java, явное импортирование входит в стандарт кодирования. Я иногда по-прежнему использую * для быстрого прототипирования, а затем расширяю списки импорта (некоторые IDE также сделают это для вас) при разработке кода.

Ответ 8

Я предпочитаю специфический импорт, потому что он позволяет мне видеть все внешние ссылки, используемые в файле, не глядя на весь файл. (Да, я знаю, что это не обязательно будет показывать полностью квалифицированные ссылки, но я избегаю их, когда это возможно.)

Ответ 9

В предыдущем проекте я обнаружил, что переход от * -импорт к конкретному импорту сократил время компиляции наполовину (от примерно 10 минут до примерно 5 минут). * -import делает компилятор для поиска каждого из пакетов, перечисленных для класса, соответствующего тому, который вы использовали. Хотя это время может быть небольшим, оно добавляется для больших проектов.

Побочным эффектом * -import было то, что разработчики копировали и вставляли общие строки импорта, а не думали о том, что им нужно.

Ответ 10

В DDD книге

В какой бы технологии разработки не была основана реализация, ищите способы минимизировать работу рефакторинга МОДУЛЕЙ. В Java нет возможности избежать импорта в отдельные классы, но вы можете по крайней мере импортировать целые пакеты за один раз, отражая намерение, что пакеты являются очень связными единицами, одновременно сокращая усилия по изменению имен пакетов.

И если это загромождает локальное пространство имен, это не ваша вина - виноват размер пакета.

Ответ 11

Самое главное, что импорт java.awt.* может сделать вашу программу несовместимой с будущей версией Java:

Предположим, что у вас есть класс с именем "ABC", вы используете JDK 8 и импортируете java.util.*. Теперь предположим, что Java 9 выходит, и у него есть новый класс в пакете java.util, который по совпадению также называется ABC. Ваша программа теперь не будет компилироваться на Java 9, потому что компилятор не знает, означает ли с именем "ABC" ваш собственный класс или новый класс в java.awt.

У вас не будет этой проблемы, если вы импортируете только те классы, которые явным образом из java.awt, которые вы используете.

Ресурсы

Java Imports

Ответ 12

Среди всех действительных точек, сделанных с обеих сторон, я не нашел своей основной причины избегать шаблона: мне нравится читать код и точно знать, что такое каждый класс, или если это определение не на языке или файл, где его найти. Если импортировано несколько пакетов с *, я должен искать каждый из них, чтобы найти класс, который я не распознаю. Считываемость является высшей, и я согласен, что код не должен требовать IDE для его чтения.

Ответ 13

  • Влияния во время выполнения не происходит, так как компилятор автоматически заменяет * конкретными именами классов. Если вы декомпилируете файл .class, вы никогда не увидите import...*.

  • С# всегда использует * (неявно), так как вы можете using только имя пакета. Вы никогда не можете указать имя класса вообще. Java вводит функцию после С#. (Java очень сложен во многих аспектах, но это выходит за рамки этой темы).

  • В Intellij Idea, когда вы "организуете импорт", он автоматически заменяет несколько импортов одного пакета на *. Это обязательная функция, так как вы не можете отключить ее (хотя вы можете увеличить порог).

  • Случай, указанный в принятом ответе, недействителен. Без * у вас все еще та же проблема. Вам необходимо указать имя pakcage в вашем коде, независимо от того, используете вы * или нет.

Ответ 14

Для записи: когда вы добавляете импорт, вы также указываете свои зависимости.

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