为什么在 Java 导入语句中使用通配符不好?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/147454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:55:24  来源:igfitidea点击:

Why using a wild card with a Java import statement bad?

javaimportwildcard

提问by jnancheta

It is much more convenient and cleaner to use a single statement like

使用像这样的单一语句更方便、更干净

import java.awt.*;

than to import a bunch of individual classes

而不是导入一堆单独的类

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

What is wrong with using a wildcard in the importstatement?

import语句中使用通配符有什么问题?

采纳答案by Benjamin Pollack

The only problem with it is that it clutters your local namespace. For example, let's say that you're writing a Swing app, and so need java.awt.Event, and are also interfacing with the company's calendaring system, which has com.mycompany.calendar.Event. If you import both using the wildcard method, one of these three things happens:

它唯一的问题是它使您的本地命名空间变得混乱。例如,假设您正在编写一个 Swing 应用程序,因此需要java.awt.Event,并且还与公司的日历系统交互,该系统具有com.mycompany.calendar.Event. 如果使用通配符方法导入两者,则会发生以下三种情况之一:

  1. You have an outright naming conflict between java.awt.Eventand com.mycompany.calendar.Event, and so you can't even compile.
  2. You actually manage only to import one (only one of your two imports does .*), but it's the wrong one, and you struggle to figure out why your code is claiming the type is wrong.
  3. When you compile your code there is no com.mycompany.calendar.Event, but when they later add one your previously valid code suddenly stops compiling.
  1. java.awt.Event和之间存在彻底的命名冲突com.mycompany.calendar.Event,因此您甚至无法编译。
  2. 您实际上只导入了一个(只有两个导入中的一个.*),但它是错误的,并且您很难弄清楚为什么您的代码声称类型是错误的。
  3. 当您编译代码时,没有com.mycompany.calendar.Event,但是当他们稍后添加一个时,您以前有效的代码突然停止编译。

The advantage of explicitly listing all imports is that I can tell at a glance which class you meant to use, which simply makes reading the code that much easier. If you're just doing a quick one-off thing, there's nothing explicitly wrong, but future maintainers will thank you for your clarity otherwise.

显式列出所有导入的优点是我一眼就能看出您打算使用哪个类,这只会让阅读代码变得更加容易。如果你只是做一件快速的一次性事情,没有什么明显的错误,但未来的维护者会感谢你的清晰。

回答by Jeff C

I prefer specific imports, because it allows me to see all the external references used in the file without looking at the whole file. (Yes, I know it won't necessarily show fully qualified references. But I avoid them whenever possible.)

我更喜欢特定的导入,因为它允许我查看文件中使用的所有外部引用,而无需查看整个文件。(是的,我知道它不一定会显示完全限定的引用。但我尽可能避免使用它们。)

回答by hazzen

It clutters your namespace, requiring you to fully specify any classnames that are ambiguous. The most common occurence of this is with:

它使您的命名空间变得混乱,要求您完全指定任何不明确的类名。最常见的情况是:

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

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

It also helps make your dependencies concrete, as all of your dependencies are listed at the top of the file.

它还有助于使您的依赖项具体化,因为您的所有依赖项都列在文件顶部。

回答by Josh Segall

  1. It helps to identify classname conflicts: two classes in different packages that have the same name. This can be masked with the * import.
  2. It makes dependencies explicit, so that anyone who has to read your code later knows what you meant to import and what you didn't mean to import.
  3. It can make some compilation faster because the compiler doesn't have to search the whole package to identify depdencies, though this is usually not a huge deal with modern compilers.
  4. The inconvenient aspects of explicit imports are minimized with modern IDEs. Most IDEs allow you to collapse the import section so it's not in the way, automatically populate imports when needed, and automatically identify unused imports to help clean them up.
  1. 它有助于识别类名冲突:不同包中具有相同名称的两个类。这可以用 * 导入屏蔽。
  2. 它使依赖关系显式化,以便以后必须阅读您的代码的任何人都知道您打算导入什么以及您不打算导入什么。
  3. 它可以使某些编译更快,因为编译器不必搜索整个包来识别依赖项,尽管这对于现代编译器来说通常不是什么大问题。
  4. 现代 IDE 最大限度地减少了显式导入的不便之处。大多数 IDE 允许您折叠导入部分,使其不碍事,在需要时自动填充导入,并自动识别未使用的导入以帮助清理它们。

Most places I've worked that use any significant amount of Java make explicit imports part of the coding standard. I sometimes still use * for quick prototyping and then expand the import lists (some IDEs will do this for you as well) when productizing the code.

我工作过的大多数使用大量 Java 的地方都将显式导入作为编码标准的一部分。我有时仍然使用 * 进行快速原型设计,然后在产品化代码时扩展导入列表(某些 IDE 也会为您执行此操作)。

回答by davetron5000

Here's a vote forstar imports. An import statement is intended to import a package, not a class. It is much cleaner to import entire packages; the issues identified here (e.g. java.sql.Datevs java.util.Date) are easily remedied by other means, not reallyaddressed by specific imports and certainly do not justify insanely pedantic imports on all classes. There is nothing more disconcerting than opening a source file and having to page through 100 import statements.

这是明星进口的投票。import 语句旨在导入,而不是类。导入整个包要干净得多;此处确定的问题(例如java.sql.Datevs java.util.Date)很容易通过其他方式解决,并没有真正通过特定的导入解决,当然也不能证明所有类别的疯狂迂腐导入都是合理的。没有什么比打开源文件并翻阅 100 条导入语句更令人不安的了。

Doing specific imports makes refactoring more difficult; if you remove/rename a class, you need to remove allof its specific imports. If you switch an implementation to a different class in the same package, you have to go fix the imports. While these extra steps can be automated, they are really productivity hits for no real gain.

进行特定的导入会使重构更加困难;如果删除/重命名类,则需要删除其所有特定导入。如果将实现切换到同一包中的不同类,则必须修复导入。虽然这些额外的步骤可以自动化,但它们确实会影响生产力,没有真正的收益。

Even if Eclipse didn't do class imports by default, everyone would still be doing star imports. I'm sorry, but there's really no rational justification for doing specific imports.

即使 Eclipse 默认不进行类导入,每个人仍然会进行星型导入。我很抱歉,但确实没有进行特定导入的合理理由。

Here's how to deal with class conflicts:

以下是处理类冲突的方法:

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

回答by Scott Stanchfield

please see my article Import on Demand is Evil

请参阅我的文章按需导入是邪恶的

In short, the biggest problem is that your code can break when a class is addedto a package you import. For example:

简而言之,最大的问题是当一个类被添加到你导入的包中时,你的代码可能会中断。例如:

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

// ...

List list;

In Java 1.1, this was fine; List was found in java.awt and there was no conflict.

在 Java 1.1 中,这很好;在java.awt中找到List,没有冲突。

Now suppose you check in your perfectly working code, and a year later someone else brings it out to edit it, and is using Java 1.2.

现在假设您签入了完美运行的代码,一年后其他人拿出来编辑它,并且使用的是 Java 1.2。

Java 1.2 added an interface named List to java.util. BOOM! Conflict. The perfectly working code no longer works.

Java 1.2 向 java.util 添加了一个名为 List 的接口。繁荣!冲突。完美运行的代码不再起作用。

This is an EVILlanguage feature. There is NOreason that code should stop compiling just because a type is addedto a package...

这是一个EVIL语言功能。有原因,代码应该停止编译仅仅因为一个类型添加到包...

In addition, it makes it difficult for a reader to determine which "Foo" you're using.

此外,读者很难确定您使用的是哪个“Foo”。

回答by Michael Hall

In a previous project I found that changing from *-imports to specific imports reduced compilation time by half (from about 10 minutes to about 5 minutes). The *-import makes the compiler search each of the packages listed for a class matching the one you used. While this time can be small, it adds up for large projects.

在之前的一个项目中,我发现从 *-imports 更改为特定导入将编译时间减少了一半(从大约 10 分钟到大约 5 分钟)。*-import 使编译器搜索列出的每个包,以查找与您使用的类匹配的类。虽然这个时间可能很小,但对于大型项目来说却是累积起来的。

A side affect of the *-import was that developers would copy and paste common import lines rather than think about what they needed.

*-import 的一个副作用是开发人员会复制和粘贴常见的导入行,而不是考虑他们需要什么。

回答by hwiechers

It's notbad to use a wild card with a Java import statement.

不是不好用通配符与Java导入语句。

In Clean Code, Robert C. Martin actually recommends using them to avoid long import lists.

Clean Code 中,Robert C. Martin 实际上建议使用它们来避免长导入列表。

Here is the recommendation:

这是建议:

J1: Avoid Long Import Lists by Using Wildcards

If you use two or more classes from a package, then import the whole package with

import package.*;

Long lists of imports are daunting to the reader. We don't want to clutter up the tops of our modules with 80 lines of imports. Rather we want the imports to be a concise statement about which packages we collaborate with.

Specific imports are hard dependencies, whereas wildcard imports are not. If you specifically import a class, then that class must exist. But if you import a package with a wildcard, no particular classes need to exist. The import statement simply adds the package to the search path when hunting for names. So no true dependency is created by such imports, and they therefore serve to keep our modules less coupled.

There are times when the long list of specific imports can be useful. For example, if you are dealing with legacy code and you want to find out what classes you need to build mocks and stubs for, you can walk down the list of specific imports to find out the true qualified names of all those classes and then put the appropriate stubs in place. However, this use for specific imports is very rare. Furthermore, most modern IDEs will allow you to convert the wildcarded imports to a list of specific imports with a single command. So even in the legacy case it's better to import wildcards.

Wildcard imports can sometimes cause name conflicts and ambiguities. Two classes with the same name, but in different packages, will need to be specifically imported, or at least specifically qualified when used. This can be a nuisance but is rare enough that using wildcard imports is still generally better than specific imports.

J1:使用通配符避免长导入列表

如果您使用一个包中的两个或多个类,则使用以下命令导入整个包

导入包。*;

长长的进口清单让读者望而生畏。我们不想用 80 行导入将模块的顶部弄乱。相反,我们希望导入是关于我们与哪些包合作的简明陈述。

特定导入是硬依赖项,而通配符导入则不是。如果您专门导入一个类,则该类必须存在。但是,如果您使用通配符导入包,则不需要存在特定的类。import 语句只是在搜索名称时将包添加到搜索路径中。因此,此类导入不会创建真正的依赖项,因此它们有助于减少我们的模块耦合。

有时,一长串特定的导入可能会有用。例如,如果您正在处理遗留代码并且想要找出需要为其构建模拟和存根的类,您可以向下遍历特定导入的列表以找出所有这些类的真正限定名称,然后输入适当的存根就位。但是,这种用于特定导入的情况非常少见。此外,大多数现代 IDE 将允许您使用单个命令将通配符导入转换为特定导入列表。因此,即使在传统情况下,最好导入通配符。

通配符导入有时会导致名称冲突和歧义。两个具有相同名称但在不同包中的类需要专门导入,或者至少在使用时专门限定。这可能很麻烦,但很少见,使用通配符导入通常仍然比特定导入更好。

回答by Vinish Nain

Performance: No impact on performance as byte code is same. though it will lead to some compile overheads.

性能:由于字节码相同,因此对性能没有影响。虽然它会导致一些编译开销。

Compilation: on my personal machine, Compiling a blank class without importing anything takes 100 ms but same class when import java.* takes 170 ms.

编译:在我的个人机器上,编译一个空白类而不导入任何东西需要 100 毫秒,但导入 java.* 时相同的类需要 170 毫秒。

回答by Ivan

In DDD book

DDD 书中

In whatever development technology the implementation will be based on, look for ways of minimizing the work of refactoring MODULES . In Java, there is no escape from importing into individual classes, but you can at least import entire packages at a time, reflecting the intention that packages are highly cohesive units while simultaneously reducing the effort of changing package names.

在实现将基于的任何开发技术中,寻找最小化重构 MODULES 工作的方法。在 Java 中,导入单个类是不可避免的,但您至少可以一次导入整个包,这反映了包是高度内聚单元的意图,同时减少了更改包名称的工作。

And if it clutters local namespace its not your fault - blame the size of the package.

如果它弄乱了本地命名空间,那不是你的错——归咎于包的大小。