除了减少混乱之外,还有啥理由清理 Java 中未使用的导入?
Posted
技术标签:
【中文标题】除了减少混乱之外,还有啥理由清理 Java 中未使用的导入?【英文标题】:Any reason to clean up unused imports in Java, other than reducing clutter?除了减少混乱之外,还有什么理由清理 Java 中未使用的导入? 【发布时间】:2010-11-02 00:26:39 【问题描述】:是否有充分的理由避免在 Java 中使用未使用的 import 语句?据我了解,它们是为编译器而存在的,因此大量未使用的导入不会对编译后的代码产生任何影响。是否只是为了减少混乱并避免命名冲突?
(我之所以这么问是因为 Eclipse 会针对未使用的导入发出警告,这在我开发代码时有点烦人,因为我不想删除导入,直到我很确定我已经完成了类的设计。 )
【问题讨论】:
【参考方案1】:如果您不删除导入,我认为不会出现性能问题或类似问题。
但可能存在命名冲突,在极少数情况下,例如导入列表接口。
在 Eclipse 中,您始终可以使用快捷方式(取决于操作系统 - Win:Ctrl + SHIFT + O
和 Mac:COMMAND + SHIFT + O
)来组织导入。 Eclipse 然后清理导入部分,删除所有过时的导入等。如果您再次需要导入的东西,eclipse 会在您使用Ctrl + SPACE
完成语句时自动添加它们。所以没有必要在你的类中保留未使用的代码。
与往常一样,未使用的代码会分散您和其他人的注意力,同时阅读代码并在您的活动代码中留下一些东西,因为也许我以后需要它通常被视为不好的做法。
【讨论】:
在windows上其实是Ctrl+Shift+O。 Ctrl+Shift+O 在 Linux 上很好。在 BSD 上可能相同。 组织导入操作的另一种方法是单击ctrl+3
(至少在windwos上),然后键入导入。它显然比 ctrl+shift+O 慢,但它是一种快速找到它的方法(以及您记住或只是试图找到的许多其他操作),即使您不记得具体的快捷方式。【参考方案2】:
如果您从类路径中删除导入所引用的类,您将不会得到一个无用的愚蠢编译器错误。当您执行“使用地点”搜索时,您不会得到误报。
另一个(但这在本质上是非常具体的)是如果未使用的导入与另一个导入有命名冲突,导致您不必要地使用完全限定名称。
附录:今天构建服务器开始失败编译(甚至没有测试运行),并出现内存不足错误。它永远运行良好,签入没有对构建过程进行任何更改或可以解释这一点的重要补充。在尝试将内存设置(这是在 64 位 CentOS 上运行 64 位 JVM!)增加到远远超出客户端可以编译的范围后,我一一检查了签入。
开发人员使用并放弃了不正确的导入(他们使用了该类,自动导入它,然后意识到这是一个错误)。未使用的导入拉入了应用程序的一个单独的层,虽然 IDE 未配置为将它们分开,但构建过程是。该单一导入拖入了如此多的类,以至于编译器试图在类路径中没有相关依赖库的情况下进行编译,这导致了很多问题,以至于导致了内存不足错误。解决了这个由未使用的导入引起的问题花了一个小时。
【讨论】:
@Yishai,如果您使用 Eclipse,请查看 Save Actions,它可以在您每次保存时标准化源代码。 @EJP,虽然它们不会影响生成的字节码,但编译器需要解析它们才能理解它需要创建的字节码。 @EJP,整个附录都在讨论编译时间(“构建服务器开始编译失败”)。 我还是不明白单独的导入是如何导致这一切的? @Yishai 对不起,我不相信。你误诊了。除非实际使用了该类,否则导入应该没有这样的效果。 import 语句所做的只是告诉编译器该类在哪个包中。编译器仅在需要有关该类的类型信息时才尝试隐式编译。【参考方案3】:从纯粹主义者的角度来看,任何依赖都是对产品的“约束”,因此可能会导致以后的维护问题。
例如,假设您的程序使用 com.X.Y.Z.ObjectPool 类,然后您决定不使用它但从不删除导入。 如果其他人现在想要实例化 org.W.V.Y.ObjectPool 并仅引用 ObjectPool,他们不会收到任何警告,直到出现转换问题或调用问题。
顺便说一句,这并不是一个不切实际的场景。每次 Eclipse 询问您要导入哪个特定版本的 X,并且您从许多包中选择一个时,如果您在那里进行了导入,您可能会在不知道的情况下做出错误的选择。
无论哪种方式,您都可以要求 Eclipse 为您清理这些内容
【讨论】:
【参考方案4】:警告?让 Eclipse 自动为您清理它们。这就是 IntelliJ 所做的。如果它足够聪明地警告你,它应该足够聪明地清理它们。我建议寻找一个 Eclipse 设置来告诉它不要再这样唠叨并做点什么。
【讨论】:
这就是保存操作。就我个人而言,我喜欢 Eclipse 仅在您明确要求时更改您的代码。 @Thorbjørn:同意,特别是如果这是一个我已经停止使用一段时间但我希望很快再次添加的课程。 @Donal,嗯,这就是 Ctrl-Space 的用途。【参考方案5】:这与对维护有用的程序的清晰度有关。
如果您必须维护一个程序,您会发现每行导入一个类是多么有用。
考虑以下场景:
import company.billing.*;
import company.humanrerources.*;
// other imports
class SomeClass
// hundreds or thousands of lines here...
public void veryImportantMethod()
Customer customer;
Employee comployee;
Department dept.
// do something with them
当您修复或维护一段代码(或仅阅读它)时,了解所使用的类属于哪个包对读者很有帮助。使用如上所示的通配符导入对此没有帮助。
即使使用 IDE,您也不想悬停或跳转到声明并返回,如果您在功能方面了解当前代码所依赖的其他包和类会更容易。
如果这是用于个人项目或小型项目,那真的没关系,但对于必须由其他开发人员使用(并经过多年维护)的大型项目,这是必须具备的。
绝对没有任何性能差异。
【讨论】:
【参考方案6】:仅供参考,这让我大吃一惊,因为我不认为组织导入实际上删除了未使用的导入,我认为它只是对它们进行了排序。
在保存操作期间自动删除导入让我有些悲痛,例如,在开发或测试期间,您遇到问题并注释掉一些代码,当您保存它时,被注释掉的代码部分使用的导入被删除。有时这不是问题,因为您可以撤消 (Ctrl+Z) 更改,但有时它不是那么简单,因为您可能进行了其他更改。我还有一个问题,当我取消注释代码时(我之前已经注释掉然后保存,因此删除了该代码的导入),它会自动尝试猜测所需的导入并选择错误的导入(例如,我认为我使用了一个 StringUtils
类,它从错误的库中选择了另一个同名的类)。
我更喜欢手动组织导入,而不是将其作为保存操作。
【讨论】:
【参考方案7】:对于 Eclipse,我使用这个:窗口 -> 首选项 -> java -> 编辑器 -> 保存操作 -> 选中组织导入的复选框(那里也有很多其他有用的东西,比如格式化,使字段最终和很快..)。因此,当我保存文件时,eclipse 为我删除了 unessacry 导入。在我看来,如果您不需要某些东西,请删除它(或让它被 eclipse 删除)。
【讨论】:
【参考方案8】:您可以将未使用的导入语句注释掉,警告不会打扰您,但您可以看到您有什么。
【讨论】:
@DimaSan 实际上确实如此:问题是 我不想删除导入,直到我很确定我已经完成了类的设计。【参考方案9】:没有任何性能影响,但为了便于阅读,您可以使其干净。在 Eclipse 和 IntelliJ IDEA 中删除未使用的导入非常简单。
Eclipse
Windows / Linux - Ctrl+Shift+O
Mac - Cmd+Shift+O
IntelliJ IDEA 或 Android Studio
Windows / Linux - Ctrl+Alt+O
Mac - Cmd+Alt+O
【讨论】:
【参考方案10】:未使用的导入仍会创建依赖项。如果您没有意识到依赖只是因为未使用的导入,您可能会浪费时间更新模块版本、调查与该模块相关的漏洞报告等。
在极端情况下,仅在应用程序的类路径中提供可用的模块(即使您的代码不使用它)也会产生可利用的漏洞。例如,原本未使用的库中的反序列化小工具可能存在远程代码执行漏洞。
让您的代码更具可读性应该是清理它们的充分理由,但具有不必要的依赖项也存在真正的功能缺陷。
【讨论】:
【参考方案11】:对我来说,控制器类中的一个未使用的类导入在我在代码清理期间删除导入的类并在 git 中提交删除而不在本地测试构建之后在 Jenkins 构建中产生了编译问题。
【讨论】:
【参考方案12】:几年前,我在某处读到,每个导入的类都会在运行时与导入类一起加载。因此删除未使用的包,尤其是整个包,将减少内存开销。 虽然我认为现代版本的 java 可以处理这个问题,所以可能不再是原因了。
顺便说一下,在eclipse中你可以使用Ctrl+Shift+O来组织导入,但是你也可以配置一个"每次保存 java 文件时都会处理此类事情(以及许多其他事情)。
【讨论】:
hmm.. 如果这是这种行为,我会感到惊讶.. 我知道类在第一次使用之前不会被初始化(即调用静态初始化器),或者直到它们被自定义加载器特别请求。但如果“加载”只是指“读入内存但未处理”,则有可能,尽管我对此表示怀疑。 实际上,经过进一步思考,它应该很容易测试。使用未使用的导入编译代码,然后使用“反编译”工具查看未使用的导入是否仍然存在。如果不是,那么它们要么被编译器删除,要么只是为了方便程序员而存在。 你到底是从哪里读到的?这是完全和完全不正确的,而且一直都是。 代码引用的每个类都会被加载,不包括导入。以上是关于除了减少混乱之外,还有啥理由清理 Java 中未使用的导入?的主要内容,如果未能解决你的问题,请参考以下文章
除了按位否定运算之外,“~”在 python 中还有啥作用? [复制]
除了明显的错误配置问题之外,还有啥可能导致 Servlet 过滤器的 ClassNotFoundException?
模块化 JavaScript - 除了 CommonJS 和 AMD 之外,还有啥方法可以考虑吗?
关于客户端安全性,CORS 除了颠覆同源策略之外还有啥作用?