首页 文章

为什么使用带有Java import语句的通配符不好?

提问于
浏览
325

使用单个语句更方便,更清晰

import java.awt.*;

而不是导入一堆个别类

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

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

13 回答

  • 21

    DDD book

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

    如果它使本地命名空间混乱不是你的错 - 责怪包的大小 .

  • 140

    唯一的问题是它使你的本地命名空间变得混乱 . 例如,让's say that you'重新编写Swing应用程序,因此需要 java.awt.Event ,并且还与公司的日历系统连接,该系统具有 com.mycompany.calendar.Event . 如果使用通配符方法导入两者,则会发生以下三种情况之一:

    • java.awt.Eventcom.mycompany.calendar.Event 之间存在完全的命名冲突,因此您甚至无法编译 .

    • 您实际上只管理导入一个(两个导入中只有一个导入 .* ),但这是错误的,并且您很难弄清楚为什么您的代码声称类型错误 .

    • 当您编译代码时没有 com.mycompany.calendar.Event ,但是当它们稍后添加一个时,您之前有效的代码会突然停止编译 .

    显式列出所有导入的优点是,我可以一目了然地告诉您要使用哪个类,这使得阅读代码变得更加容易 . 如果你没有明显的错误,但未来的维护者会感谢你的清晰 .

  • 9

    这是一个投票 for 明星进口 . import语句用于导入包,而不是类 . 导入整个包更干净;这里发现的问题(例如 java.sql.Date vs java.util.Date )很容易通过其他方式弥补,而不是通过特定进口来解决,当然也不能证明所有类别的疯狂迂腐进口都是正当的 . 没有什么比打开源文件和必须翻阅100个import语句更令人不安的了 .

    进行特定的导入会使重构变得更加困难;如果删除/重命名某个类,则需要删除其特定导入的 all . 如果将实现切换到同一个包中的其他类,则必须修复导入 . 虽然这些额外的步骤可以实现自动化,但它们确实可以提高 生产环境 效率 .

    即使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在java.util中添加了一个名为List的接口 . 繁荣!冲突 . 完美的代码不再有效 .

    这是EVIL语言功能 . 没有理由代码应该停止编译只是因为类型被添加到包...

    此外,它使读者难以确定您正在使用哪个“Foo” .

  • 2

    使用带有Java import语句的通配符并不错 .

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

    以下是建议:

    J1:使用通配符避免长导入列表如果从包中使用两个或多个类,则使用导入包导入整个包 . *;很长的进口清单令读者望而生畏 . 我们不希望使用80行导入来混淆模块的顶部 . 相反,我们希望导入是关于我们与哪些软件包协作的简明陈述 . 特定导入是硬依赖性,而通配符导入则不是 . 如果您专门导入一个类,那么该类必须存在 . 但是如果导入带有通配符的包,则不需要存在特定的类 . 在搜索名称时,import语句只是将包添加到搜索路径中 . 因此,这些导入不会产生真正的依赖关系,因此它们可以使我们的模块更少耦合 . 有时,特定导入的长列表可能很有用 . 例如,如果您正在处理遗留代码,并且想要找出构建模拟和存根所需的类,则可以在特定导入列表中查找所有这些类的真正限定名称然后放入适当的存根 . 但是,这种用于特定进口的用途非常多罕见 . 此外,大多数现代IDE允许您使用单个命令将通配符导入转换为特定导入列表 . 因此,即使在传统情况下,最好导入通配符 . 通配符导入有时会导致名称冲突和歧义 . 具有相同名称但在不同包中的两个类需要专门导入,或者至少在使用时特别限定 . 这可能是令人讨厌的,但是很少见,使用通配符导入通常仍然比特定导入更好 .

  • 12

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

    import java.util.*;
    import java.awt.*;
    
    ...
    List blah; // Ambiguous, needs to be qualified.
    

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

  • 1

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

    Compilation :在我的个人计算机上,编译空白类而不导入任何内容需要100毫秒但导入java时相同的类 . *需要170毫秒 .

  • 18
    • 它有助于识别类名冲突:不同包中具有相同名称的两个类 . 这可以用* import掩盖 .

    • 它使依赖项显式化,以便以后必须阅读代码的任何人都知道您要导入的内容以及您不想导入的内容 .

    • 它可以使编译速度更快,因为编译器不必搜索整个包来识别依赖性,尽管这对现代编译器来说通常不是很大 .

    • 使用现代IDE可以最大限度地减少显式导入的不便之处 . 大多数IDE允许您折叠导入部分,因此它不会妨碍,在需要时自动填充导入,并自动识别未使用的导入以帮助清理它们 .

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

  • 6

    我更喜欢特定的导入,因为它允许我在不查看整个文件的情况下查看文件中使用的所有外部引用 . (是的,我知道它不一定会显示完全合格的参考文献 . 但我尽可能避免它们 . )

  • 2

    在之前的项目中,我发现从* -imports更改为特定导入会将编译时间缩短一半(从大约10分钟缩短到大约5分钟) . * -import使编译器搜索列出的每个包中与您使用的类匹配的类 . 虽然这个时间可能很短,但它会增加大型项目 .

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

    最重要的一点是导入 java.awt.* 可能会使您的程序与未来的Java版本不兼容:

    假设您有一个名为"ABC"的类,您正在使用JDK 8并导入 java.util.* . 现在,假设Java 9出来了,它在包 java.util 中有一个新类,巧合也恰好称为"ABC" . 您的程序现在无法在Java 9上编译,因为编译器不知道名称"ABC"是指您自己的类还是 java.awt 中的新类 .

    当您从实际使用的 java.awt 中仅显式导入这些类时,您将不会遇到此问题 .

    资源:

    Java Imports

  • 402
    • 没有运行时影响,因为编译器会自动用具体的类名替换* . 如果您反编译.class文件,您将永远不会看到 import ...* .

    • C# always 使用*(隐式),因为你只能 using 包名 . 你永远不能指定类名 . Java在c#之后引入了这个特性 . (Java在很多方面都很棘手,但它超出了这个主题) .

    • 在Intellij Idea中,当您进行“组织导入”时,会自动进行用*替换同一包的多个导入 . 这是一项强制性功能,因为您无法将其关闭(尽管您可以增加阈值) .

    • 接受的回复列出的案例无效 . 没有你仍然有同样的问题 . 无论您是否使用,都需要在代码中指定pakcage名称 .

  • 8

    在双方所有的有效观点中,我没有认识到这个定义是不是't in the language or the file, where to find it. If more than one package is imported with * I have to go search every one of them to find a class I don' . 可读性是至关重要的,我同意代码不应该需要IDE来阅读它 .

相关问题