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

问题描述 投票:353回答:14

这是更方便和更清洁的使用像一个语句

import java.awt.*;

比进口一堆个人类

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

什么是错在import语句中使用通配符?

java import wildcard
14个回答
460
投票

与它唯一的问题是,它杂波当地的命名空间。例如,假设你正在编写一个Swing应用程序,因此需要java.awt.Event,并且也与公司的日程系统,它具有com.mycompany.calendar.Event接口。如果您导入使用通配符法两种,这三件事情之一发生:

  1. 你有java.awt.Eventcom.mycompany.calendar.Event之间的直接命名冲突,所以你甚至不能编译。
  2. 实际上,你只能管理导入一个(只有你的两个进口人做.*),但它是错误的,你很难弄清楚为什么你的代码声称类型是错误的。
  3. 当您编译代码没有com.mycompany.calendar.Event,但是当他们以后再添加一个你以前有效的代码突然停止编译。

中明确列出所有进口的优点是,我可以在你想用的,它只是使阅读的代码更加容易哪一类一眼就能看出。如果你只是做一个快速一次性的事情,没有什么明确的错,但将来的维护人员会感谢你的清晰,否则。


6
投票

DDD book

在任何开发技术的实施将依据,寻找减少重构模块的工作方式。在Java中,没有从导入到单独的类逃跑,但你至少可以在进口时整个包,反映了意图封装高度凝聚力的单位,同时降低改换包装名称的努力。

如果它杂波局部命名空间它不是你的错 - 怪包的大小。


2
投票

其中最重要的是,进口java.awt.*可以使你的程序有一个未来的Java版本不兼容:

假设你有一个名为“ABC”类,你正在使用JDK 8和导入java.util.*。现在,假设Java的9出来,它已在包一类新java.util是巧合也恰好被称为“ABC”。你的程序将无法编译Java的9,因为如果一个名为“ABC”你的意思是你自己的类或java.awt新类的编译器不知道。

当你明确地java.awt你实际使用只导入这些类,你不会有这个问题。

资源:

Java Imports


2
投票

在双方提出的所有有效点我还没有发现我的主要理由,以避免通配符:我希望能够读取的代码,直接了解每类是什么,或者如果它的定义是不是在语言或该文件,在哪里可以找到它。如果有多个包导入与*我必须去寻找他们每个人找一个类,我不认识。可读性是至高无上的,我同意代码不应该需要一个IDE读取它。


2
投票
  • 没有运行的影响,因为编译器会自动替换具体的类名*。如果你反编译的.class文件,你绝不会看到import ...*
  • C#总是使用*(隐含的),你可以只using包名。你永远不能在所有指定类名。 Java的介绍后,C#中的功能。 (Java是在许多方面如此棘手,但它超出了这个话题)。
  • 在IntelliJ IDEA的,当你“组织导入”,它会自动替换同一软件包的多个进口与*。这是因为你不能把它关掉(虽然你可以增加阈值)一个mandantory功能。
  • 被接受的回复中列出的情况下是无效的。如果没有*您仍然得到了同样的问题。你需要在你的代码指定pakcage名字无论你使用*或没有。

2
投票

为了记录:当您添加一个导入,您也表明你的依赖。

你可以很快看到什么是文件的依赖关系(不包括同一个命名空间中的类)。


173
投票

下面是星进口的一票。 import语句旨在导入包,而不是一个类。它是干净多了导入整个包;这里发现的问题(例如java.sql.Date VS java.util.Date)很容易通过其他方式弥补,没有真正具体的进口解决,当然不证明所有类别疯狂迂腐进口。没有什么比通过100个import语句打开源文件,并具有网页更令人不安。

做具体的进口使得重构更加困难;如果删除/重命名类,你需要删除所有其特定的进口。如果你在同一个包切换的实现,以不同的类,你必须去解决的进口。虽然这些额外的步骤可以自动化,他们真的没有真正的收获生产力命中。

即使Eclipse中没有默认做类进口,大家还是会做明星的进口。我很抱歉,但有真正做具体的进口没有任何合理的理由。

以下是如何对付阶级矛盾:

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

158
投票

请参阅我的文章Import on Demand is Evil

总之,最大的问题是,当一个类被添加到您导入包你的代码可以打破。例如:

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

// ...

List list;

在Java 1.1,这是罚款;名单java.awt中发现,也没有冲突。

现在假设你在你的工作完美的代码检查,并在一年后别人带来它进行编辑,并使用Java 1.2。

Java 1.2的附加的接口名为List到java.util中。繁荣!冲突。这个完美的工作代码不再起作用。

这是一个邪恶的语言功能。没有理由的代码应该停止编译仅仅因为一个类型添加到包...

此外,它很难让读者来确定哪些“富”你使用。


63
投票

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

Clean Code,罗伯特C.马丁居然建议使用它们,以避免长时间导入列表。

这里是建议:

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

如果您使用两个或多个类从一个包,然后导入整个包

导入包*。

进口的长列表是艰巨的读者。我们不希望扰乱我们的模块的顶部与80线的进口。相反,我们要进口约为哪些软件包与我们合作的简要陈述。

具体进口硬相关,而通配符进口都没有。如果你特别导入类,则必须存在一个类。但是,如果你导入包使用通配符,没有特别的类需要存在。狩猎名称时import语句只是增加了包的搜索路径。因此,没有真正的依赖是否受此类进口创建的,因此它们有助于保持我们的模块少耦合的。

有些时候,特定进口的一长串可能是有用的。例如,如果你正在处理遗留代码,你想找出你需要搭建,你可以走专用进口清单嘲弄和存根找出所有这些类的真正合格的名称,然后放什么班在地方相应的存根。然而,这种使用特定的进口是非常罕见的。此外,大多数现代IDE可以让你的通配符进口的某些特定进口的列表转换用一条命令。因此,即使在传统情况下,它是更好地导入通配符。

通配符进口有时会引起名称冲突和模糊性。两个具有相同的名称,但在不同的包,将需要专门进口的,或至少明确限定的使用时。这可能是一个滋扰,但足够罕见的,使用通配符进口仍普遍高于具体的进口更好。


22
投票

它杂波您的命名空间,需要您充分指定不明确的任何类名。这种情况最经常发生的事情是:

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

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

它也可以让你的依赖具体的,因为所有的依赖都在文件的顶部列出。


21
投票

性能:作为字节代码对性能没有影响是一样的。虽然它会导致一些编译开销。

编辑:我个人的机器上,编译一个空白的类,但不导入任何需要100毫秒,但相同的类时,进口的Java *需要170毫秒。


15
投票
  1. 它有助于查明类名冲突:在具有相同名称的不同包两班。这可以通过*进口所掩盖。
  2. 这使得依赖关系明确,使任何人谁也看后面的代码知道你的意思是导入和你不是故意要导入的内容。
  3. 它可以使一些编译更快,因为编译器不必搜索整个包来识别depdencies,尽管这通常不是一个巨大的交易与现代编译器。
  4. 明确进口的不便方面最小化与现代的IDE。大多数IDE让你崩溃的进口部分,所以它不是在路上,在需要时自动填充进口,并自动识别未使用的导入,以帮助清理它们。

我工作过的大多数地方使用Java的任何显著量使编码标准的明确进口一部分。我有时仍然使用*快速原型,然后扩大进口清单产品化的代码时(有些IDE会为你做这个也一样)。


10
投票

我更喜欢具体的进口,因为它让我看到文件中使用,而不看整个文件中的所有外部引用。 (是的,我知道这并不一定会表现出完全合格的引用。但我避免他们只要有可能。)


9
投票

在以前的项目中,我发现,从*改变-imports具体的进口减少编译时间的一半(约10分钟至约5分钟)。在* -import使每个匹配的,你所使用的一类列出的软件包编译器搜索。虽然这个时候可以小,但对大型项目增加了。

在* -import的A面影响是,开发者复制并粘贴常见的进口线,而不是考虑他们需要什么。

© www.soinside.com 2019 - 2024. All rights reserved.