代码之家  ›  专栏  ›  技术社区  ›  James Cadd

Eclipse/Java——导入Java(命名空间)是有害的。*?

  •  17
  • James Cadd  · 技术社区  · 15 年前

    为什么Eclipse在导入类型时采用细粒度方法?在C中,我习惯了“使用system.windows.controls”和使用它,但是Eclipse喜欢单独导入我引用的每个小部件(使用ctrl+shift+o快捷方式)。如果我知道在导入整个命名空间时需要多个类型,那么导入整个命名空间是否有任何危害?

    11 回复  |  直到 15 年前
        1
  •  10
  •   coobird    15 年前

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

    比如说,我想编程使用 ArrayList AWT应用程序中使用A的Java集合框架的类 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 类与A java.util.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()
    

    因此,有些情况下使用通配符包 进口 可能导致问题。

        2
  •  15
  •   Kristopher Ives    15 年前

    Eclipse有一个很好的设置,叫做“在窗口中组织导入”->首选项对话框,允许您在 n 类是从包中使用的,执行通配符导入。我用它 n 通常为2或3。

        3
  •  12
  •   axtavt    15 年前

    有人可以在不使用IDE的情况下读取代码——在这种情况下,非通配符导入将帮助他确定代码中使用的类。

        4
  •  8
  •   Pascal Thivent    15 年前

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

    在没有通配符的情况下使用时,该指令显式地告诉编译器在类路径中查找一个特定的文件。使用通配符,指令指示编译器查找命名包 每次需要匹配任何名称时,都要在该包中搜索可能的匹配项。对于编译器来说,后一个版本可能要比前一个版本长(一点)。

    也就是说, 进口 指令不能影响 运行时 以任何方式执行代码。然而, 进口 指令确实影响编译时间。此外,我发现使用 进口 使用通配符会降低代码的可读性。

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

    • 使用import语句没有运行时成本
    • 导入时编译过程可能会花费更多的时间。 陈述
    • 使用通配符导入编译过程可能会花费更多的时间 陈述
    • 为了提高可读性,通配符导入语句对于 除了一次性课程
    • 非通配符导入语句的编译开销为 次要,但它们提供可读性 因此最佳实践是使用 他们
        5
  •  5
  •   Community CDub    8 年前

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

    当我使用尚未导入的类时,我只使用ctrl+space强制导入,导入将自动进行。然后,在重构类以删除不再使用的任何导入之后,按ctrl+shift+o。

        6
  •  2
  •   TofuBeer    15 年前

    在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被添加,代码不再编译,因为编译器不知道需要哪个列表(awt或util)。您可以通过在导入结束时添加“导入Java.AWT.List.”来修复它,但关键是您必须做些事情来修复它。

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

    1. 很清楚每节课的目的地 从
    2. 如果你有大量进口 这个班可能做得太多了 应该分开。这是一个 “代码嗅觉”。
        7
  •  1
  •   Uri    15 年前

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

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

    尽管如此,我承认我很懒。我通常会预先导入包中的所有内容,然后让Eclipse根据我实际使用的内容来组织它。

        8
  •  1
  •   duffymo    15 年前

    导入包/名称空间中的所有类没有任何危害,但我认为最好包括每个单独的类。它使开发人员更清楚地了解每个类的具体来源。

    如果你使用的是像Intellij这样的功能强大的IDE,这是没有问题的。我可以想象Eclipse和NetBeans也可以管理导入。它将为您添加代码并从视图中折叠它们,这样它们就不会使窗口杂乱无章。什么更容易?

        9
  •  0
  •   fastcodejava    15 年前

    不会伤害代码。作为一般原则,如果不打算使用,为什么要导入某些内容?

        10
  •  0
  •   FloppyDisk    15 年前

    如果编写一些Java代码,例如

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

    而且您还没有将LinkedList导入到您的项目中,Eclipse会询问您是否要导入它。因为您只使用LinkedList,而不使用其他任何方法,所以它只导入LinkedList。如果您在同一个项目中执行其他操作,例如
    ArrayList<foo> alist = new ArrayList<foo>()

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

    import java.namespace.*

    去把你需要的其他东西带来。只要您导入包含您所引用的项目(如扫描仪、LinkedList等)的包和库,Eclipse就不会在意。

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

        11
  •  0
  •   Thorbjørn Ravn Andersen    15 年前

    显式导入每个类在短名称(例如代理)和长名称(例如Java.Lang.Exchange代理)之间进行硬绑定,而不是松散绑定,表示可能存在一个。 java.lang.reflect.* , java.io.* java.net.* 或者其他一些通配符导入。

    如果出于某种原因,这可能是个问题 另一个 名为proxy的类出现在 Java.IO.* Java.NET.* 或者您自己的代码,因为编译器不知道如果显式导入java.lang.reflect.proxy,您希望使用哪个代理类。

    上面的例子是不可原谅的。Java.NET.Server类在Java 5中被引入,如果它被写为上面的提示,则会破坏代码。参见官方的Sun解释如何规避通配符问题 http://java.sun.com/j2se/1.5.0/compatibility.html

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