【问题标题】:Import package.* vs import package.SpecificType [duplicate]导入包。*与导入包。特定类型 [重复]
【发布时间】:2010-09-16 07:00:18
【问题描述】:

是否会假设在编写导入加载一个包中的所有类型的开销方面有任何差异(import java.*);不仅仅是特定类型(即import java.lang.ClassLoader)?第二种使用方式会比另一种更可取吗?

【问题讨论】:

标签: java import overhead


【解决方案1】:

看看java API,你会看到很多同名的类和接口在不同的包里。

例如:

java.lang.reflect.Array
java.sql.Array

因此,如果您导入 java.lang.reflect.*java.sql.*,您将在 Array 类型上发生冲突,并且必须在您的代码中完全限定它们。

导入特定的类可以省去这个麻烦。

【讨论】:

  • 命名冲突!我确实忽略了那个。 +1 给你
  • @Chris 使用import a.b.*对编译时间有什么影响?
  • @saurabheights 我们在乎吗?没有故意的。编译时间通常不是开发问题,除非它变得荒谬。这是我们关心的运行时间。
【解决方案2】:

进行 import .* 与导入特定类型相比,没有性能或开销成本。但是,我认为永远不要使用 import .* 是一个最佳实践.

【讨论】:

  • 实际上,我理解避免使用 import package.* 作为编译器的优化,因为它允许编译器在编译当前文件时更好地定位类文件查找。
  • 怀疑这会有任何优化问题。除了命名冲突,您可以使用特定的导入语句轻松避免它们。即使您懒得输入所有导入,现代 IDE 也会为您完成...
【解决方案3】:

这其实是一个很糟糕的问题。

假设你写

import a.*;
import b.*;
...
Foo f;

并且类 Foo 存在于包 a 中。

现在你检查你完美编译的代码,六个月后,有人将类 Foo 添加到包 b。 (可能是第三方库在最新版本中添加了类)。

噗!现在您的代码拒绝编译。

从不使用按需导入。太邪恶了!

更多详情请见http://javadude.com/articles/importondemandisevil.html

RE 性能:

import a.*;

import a.X;

在运行时没有区别。编译器将解析的类名硬连线到生成的 .class 文件中。

【讨论】:

  • 我打算发布一个指向您文章的链接(我昨天读过),但我想您可能想自己做。 :)
  • 它不是"邪恶",它只是有一个你应该注意的缺点。
  • 不——这是一个邪恶的功能,当代码被添加到外部库时,它允许破坏。
  • @Scott 实际上,其他编程语言(例如 C#)在不导入特定类的情况下也可以。
  • 有什么优势?借助当今自动添加和折叠/折叠导入的 IDE 和编辑器,我看到按需导入的 优势。当唯一发生的事情是将新类添加到 jar 时,允许先前工作的代码中断的语言功能绝对是邪恶的。
【解决方案4】:

少数派观点:在我的代码中,我倾向于使用来自几个包的大量类以及一些奇怪的类。我喜欢保持我的进口清单很小,这样我就可以一眼看出发生了什么。为此,我将阈值设置为 4 个班级。除此之外,Eclipse 将使用 * 作为我的代码。我发现这使我的包导入可读,并且当我查看课程时,我倾向于将它们称为我做的第一件事,以回答以下问题:它与谁交谈?

关于名称冲突:您从两个具有竞争类名的包中导入四个或更多类的可能性有多大?如果超过 10% 的时间,您可能需要考虑您的类所依赖的包的数量(例如,将其重构为更小的类)。

【讨论】:

  • 我同意;我在实践中只遇到过 AWT List 与 util List 的冲突,然后我通常只为我想要的那个添加一个特定的导入,通常是集合。
  • @Software Monkey,确实如此。包的全部意义在于它们是粘在一起的类,这就是 * 导入背后的原因。
【解决方案5】:

在寻找更多信息后,我发现了这个网站,它的解释非常好。 Import issueDoes using * in an import statement affect performance?

这两种风格之间是否存在效率问题?可能,但由于导入声明实际上并没有将任何内容导入您的程序,因此任何差异都非常小。请记住,在编译单元的顶部有一个隐式导入 java.lang.*,而 JDK 1.2.2 中的 java.lang 包含 75 个类和接口。使用一个人为示例的实验,一个必须查找数千个类名使用的示例,显示编译速度的变化可以忽略不计。因此,在选择一种格式而不是另一种格式时,编译性能可能不应被视为一个因素。

还有一个关于进口申报的最后一个兴趣点。假设您使用内部类:

package P;

public class A {
    public static class B {}
}

如果你想从另一个编译单元访问 A,你说:

import P.*;

或: 进口PA; 但是如果你想无条件访问B,你需要说:

import P.A.*;

或: 进口P.A.B; 其中第一个使包 P 中的类 A 中的类型可用。第二个使包 P 中的类 A 中的类型 B 可用。

【讨论】:

    【解决方案6】:

    从不使用 import xxx.* 的一个很好的理由是对dependencies 有一个清晰的认识。

    您可以更快地知道您正在使用另一个包的特定类,因为它列在源文件的开头。

    【讨论】:

    • 如果你的导入列表有 70 或 200 行长,你就不再有清晰的依赖关系了。
    • 但这不是 import 语句的错,这是你的错。
    • 我认为,如果您使用该类的 3 个以上的类,最好使用 .*
    【解决方案7】:

    我倾向于使用任何 IDE 默认值。我发现这并不是真正值得担心的事情,因为它不会影响性能,并且可以使用各种工具来检查依赖关系。

    【讨论】:

      【解决方案8】:

      如果要从同一个包中导入超过 20 个类,最好使用 import xxx.*。 “清洁代码”也有利于导入整个包。

      【讨论】:

        【解决方案9】:

        导入在字节码级别无关紧要,因此应该没有运行时差异。

        我发现最好: a)通过列出所有进口来明确 b) 让您的 IDE 管理它。任何主要的 IDE 都可以自动更新、排序和完成您的导入。

        我发现 a) 在在 IDE 重构的上下文之外进行手动重新打包时会派上用场。例如,当营销更改您的产品名称并决定您的所有包裹都应该更改名称时。

        【讨论】:

          【解决方案10】:

          这更像是一种很好的编码实践,因为任何阅读您的代码的人只需查看文件顶部的导入块即可立即知道特定类使用了哪些类,而您必须深入了解您是否使用通配符。

          【讨论】:

          • 不,他们不会;他们会知道曾经使用过的所有类 - 随着代码的老化,有些类可能已被删除。
          • 像 Eclipse 这样的现代 IDE 似乎在标记未使用的导入以及在将鼠标悬停在类名上时显示完全限定的类名方面做得很好,所以我不确定“有挖”的说法是。再说一次,我也让我的 IDE “折叠”导入,这样它们就不会妨碍我,所以我通常不太关心它们是否是通配符导入是专门命名的类。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-09-13
          • 1970-01-01
          • 2020-08-10
          • 2021-09-20
          • 2015-05-30
          • 1970-01-01
          相关资源
          最近更新 更多