Eclipse/Java - 导入 java.(namespace).* 有害吗?

Posted

技术标签:

【中文标题】Eclipse/Java - 导入 java.(namespace).* 有害吗?【英文标题】:Eclipse/Java - is it harmful to import java.(namespace).*? 【发布时间】:2010-12-31 07:18:46 【问题描述】:

为什么 Eclipse 在导入类型时采用细粒度的方法?在 C# 中,我习惯于“使用 System.Windows.Controls”并完成它,但 Eclipse 更喜欢单独导入我引用的每个小部件(使用 Ctrl+Shift+O 快捷方式)。如果我知道我需要多个类型,那么导入整个命名空间有什么害处吗?

【问题讨论】:

顺便说一句,您还可以在保存时组织导入,而无需每次都点击Ctrl+Shift+O。在首选项中选中“保存操作”。 这是一个您可以在 Eclipse 和其他 IDE 中更改的选项。 Why is using a wild card with a Java import statement bad? 的可能重复项 【参考方案1】:

Eclipse 在 Window -> Preferences 对话框中有一个名为“Organize Imports”的很棒的设置,它可以让你说当 N 个类从包中使用时,进行通配符导入。我通常在 N=2 或 3 时使用它。

【讨论】:

是的,static 进口也有它,但无论如何谁真正使用它们 ;) 任何使用 JUnit 4 注释的人! +1。我已经使用 eclipse 有一段时间了,并没有意识到它的存在。会让我的生活更轻松。 FWIW:Netbeans 中提供了相同的选项。 CTRL + SHIFT + O 是热键 btw【参考方案2】:

有人可以在没有 IDE 的情况下阅读您的代码 - 在这种情况下,非通配符导入将帮助他确定您的代码中使用了哪些类。

【讨论】:

但是,只有在对文件的每次后续更新也相应地更新了导入列表时,这才是正确的。不使用 IDE 的维护者不太可能知道什么时候应该删除 import 语句,因为将它们保留在里面并不是错误。因此,实际上,它更有可能帮助非 IDE 用户弄清楚该类的用途做。【参考方案3】:

通配符包导入可能导致的唯一危害是,如果多个包中存在多个同名类,则会增加命名空间冲突的可能性。

例如,我想在 AWT 应用程序中使用 Java Collections Framework 的 ArrayList 类进行编程,该应用程序使用 List GUI 组件来显示信息。举个例子,假设我们有以下内容:

// 'ArrayList' from java.util
ArrayList<String> strings = new ArrayList<String>();

// ...

// 'List' from java.awt
List listComponent = new List()

现在,为了使用上述内容,必须至少导入这两个类:

import java.awt.List;
import java.util.ArrayList;

现在,如果我们要在包 import 中使用通配符,我们会得到以下结果。

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

但是,现在我们有一个问题!

有一个java.awt.List 类和一个java.util.List,所以提到List 类是不明确的。如果我们想消除歧义,就必须使用完全限定的类名来引用List

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

ArrayList<String> strings = new ArrayList<String>();

// ...

// 'List' from java.awt -- need to use a fully-qualified class name.
java.awt.List listComponent = new java.awt.List()

因此,在某些情况下,使用通配符包import 可能会导致问题。

【讨论】:

Java 中的命名空间冲突是否足够普遍,以至于您认为不导入 * 命名空间是最佳实践? @James:Java 中的命名空间冲突非常普遍。比 C# 多得多。在我看来,精度越高越好。 真的不经常;这取决于您正在使用的 API。但是无论如何您都不需要手动编写导入,Eclipse 会将它们折叠起来,因此您甚至看不到它们,所以我不会担心! :) 另一个例子是 java.util.Date 和 java.sql.Date 问题比日期或列表或代理要大得多。举一个例子,这是我正在处理的程序中的“Node”类的替代包列表:com.sun.corba.se.impl.orbutil.graph; com.sun.org.apache.bcel.internal.classfile; com.sun.org.apache.xalan.internal.xstlc.runtime; javax.xml.soap;org.apache.bcel.classfile; org.apache.xalan.xsltc.runtime; org.hibernate.hql.ast.tree; org.jboss.cache; org.jboss.dom4j; org.jboss.mx.metadata.AttributeOperationResolver; org.jgroups.blocks.ReplicatedTree; org.jgroups.demos.wb; org.w3c.dom; sun.org.mozilla.javascript.internal .【参考方案4】:

import 指令是一个 compiler 指令,它告诉编译器在哪里寻找一个类,并且允许不必总是使用完全限定的类名,例如java.util.HashMap。但是导入指令本身不会放入已编译的字节码文件中,编译器会将完全限定名称编译到 .class 文件中。

当不使用通配符时,该指令明确告诉编译器在类路径中查找一个特定文件。使用通配符,该指令告诉编译器查找命名包在每次需要匹配任何名称时在该包中搜索可能的匹配项。后一个版本的编译器可能会比前一个版本花费(一点)更长的时间。

换句话说,import 指令不能以任何方式影响运行时代码执行。但是,import 指令确实会影响编译时间。此外,我发现将import 与通配符一起使用会降低代码的可读性。

实际上,javaperformancetuning.com 这个月的cost of import statements 问题完美地总结了这一点:

使用 import 语句没有运行时成本 导入时编译过程可能需要更多时间 声明 使用通配符导入编译过程可能需要更多时间 声明 为了提高可读性,通配符导入语句对于 除了一次性课程 非通配符导入语句的编译开销为 次要的,但它们具有可读性 好处,所以最好的做法是使用 他们

【讨论】:

【参考方案5】:

我不认为通配符导入对性能有任何影响(如果有,我认为它只会在编译时发生)。但是就像这个SO post points out,如果你使用它们,你可能会有类名重叠。

当我使用尚未导入的类时,我只是使用 Ctrl+Space 强制导入,并且导入会自动发生。然后我在重构一个类以删除任何不再使用的导入后按 Ctrl+Shift+O。

【讨论】:

【参考方案6】:

在 JDK 1.2 之前,此代码可以正常编译:

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

public class Foo

    // List is java.awt.List
    private List list;

在 JDK 1.2 中添加了 java.util.List,代码不再编译,因为编译器不知道需要哪个 List(awt 或 util)。您可以通过添加“import java.awt.List;”来修复它在导入结束时,但关键是你必须做一些事情来修复它。

我个人使用单一导入而不是按需导入有两个原因:

    很清楚每个类的来源 来自 如果你有大量的进口 这门课可能做得太多了 并且应该分开。它是一个 “代码味道”。

【讨论】:

【参考方案7】:

从纯粹主义者的角度来看,每次导入都会产生依赖关系和潜在的冲突。进口被视为必要的邪恶,因此它们被最小化。导入另一个带有 * 的包就像写一张空白支票。像这样导入两个包就像让某人可以在您的帐户之间转移资金。

从实际的角度来看,这通常是有道理的,因为不同的项目和库对不同的概念使用惊人的相似名称。或者,假设您从包 A 导入所有内容,然后从包 B 导入所有内容,并使用包 B 中的某个类 C。如果稍后有人将名为 C 的类添加到包 A,您的代码可能会中断!

话虽如此,我承认我很懒。我通常会预先导入包中的所有内容,然后让 Eclipse 根据我的实际使用情况为我整理。

【讨论】:

【参考方案8】:

在包/命名空间中导入所有类没有害处,但我认为最好包含每个单独的类。它使追随你的开发人员更清楚每个类的来源。

如果您使用的是 IntelliJ 等功能强大的 IDE,这不是问题。我想 Eclipse 和 NetBeans 也可以管理导入。它将为您添加代码并将它们从视图中折叠起来,这样它们就不会弄乱窗口。还有什么比这更容易的?

【讨论】:

【参考方案9】:

不会损害代码。作为一般原则,如果您不打算使用,为什么要导入一些东西?

【讨论】:

在回答您的问题时,我将原始问题的最后一句话包括在内:如果我知道我需要多个类型,那么导入整个命名空间有什么害处吗?我>【参考方案10】:

如果你写一些java代码比如

LinkedList<foo> llist = new LinkedList<foo>()  

如果您还没有将 LinkedList 导入到您的项目中,Eclipse 会询问您是否要导入它。由于您只使用 LinkedList 而没有别的,它只会导入 LinkedList。如果你在同一个项目中做其他事情比如ArrayList&lt;foo&gt; alist = new ArrayList&lt;foo&gt;()

然后 Eclipse 也会说你需要导入 ArrayList,没有别的了。 Eclipse 仅根据您所做的任何库调用导入您需要的内容。如果您需要同一个库中的多个类型或项目,使用

import java.namespace.*

继续并带入您需要的其他物品。只要您导入包含您引用的项目(例如扫描仪、链接列表等)的包和库,Eclipse 就不会在意。

从可读性的角度来看,这是一个不同的问题。如果您希望人们明确知道您正在导入什么,那么调用每个小部件或包可能是有序的。如果您在标准库中使用来自同一个包的许多不同函数,这可能会变得相当乏味,并且可能会使您的文件头很长,因此使用 .* 通配符。通过通配符导入并没有什么坏处,它真的归结为您的编码标准以及您希望类标题的透明度。

【讨论】:

【参考方案11】:

显式地导入每个类会在短名称(例如 Proxy)和长名称(例如 java.lang.reflect.Proxy)之间提供一个硬绑定,而不是松散绑定说java.lang.reflect.* 中可能有一个, java.io.*java.net.* 或您拥有的其他通配符导入。

如果出于某种原因另一个名为 Proxy 的类出现在 java.io.*java.net.* 或您自己的代码中的某处,这可能是一个问题,因为编译器不知道哪个 Proxy 类如果你明确导入 java.lang.reflect.Proxy,你会想要它。

上面的例子不是人为的。 java.net.Proxy 类是在 Java 5 中引入的,如果按照上面的提示编写,它会破坏您的代码。有关如何规避通配符问题的 Sun 官方说明,请参阅 http://java.sun.com/j2se/1.5.0/compatibility.html

(通配符导入只是为那些不使用 IDE 的人维护导入语句的一种便利机制。如果您使用 IDE,那么让它帮助您:)

【讨论】:

以上是关于Eclipse/Java - 导入 java.(namespace).* 有害吗?的主要内容,如果未能解决你的问题,请参考以下文章

eclipse java项目中明明引入了jar包 为啥项目启动的时候不能找到jar包

Eclipse java调试:找不到源

加载就绪项目 - Eclipse Java EE

Eclipse Java Android - 如果没有 Google Play 服务,此应用程序将无法运行

Spark+ECLIPSE+JAVA+MAVEN windows开发环境搭建及入门实例附详细代码

Selenium_webdriver+java+TestNG入门UI自动化