为什么要定义多个导入?

时间:2013-04-06 23:54:27

标签: java import wildcard

考虑以下import语句:

import java.io. *; //有意义

导入javax.servlet。*;

导入javax.servlet.http。*;

是不是我们已经包含了“import javax.servlet。;”因此它会自动包含另一个import语句,也就是“import javax.servlet.http。;”?

为什么“导入javax.servlet.http。*”是为http?

明确定义的

如果我错了,请澄清并告诉我。

3 个答案:

答案 0 :(得分:1)

否,当您导入某些东西时,您只导入一个特定的类,或者导入该包,并导入该属性的所有类,而不是属于该包的子包的类。

每个包都包含一些相关的类和子包。子包中的类不一定与父包中的类相关。因此,导入这些也没有意义。通过这种方式,您可以避免不必要的导入并保持项目清洁。

示例:
假设您正在为GUI应用程序构建一个View类,您可能希望将这些问题分开,这样您就可以在视图中使用JComponents,在控制器中使用Listeners

因此,在您的视图中,您将导入:import javax.swing.*;这样您将获得所有JComponent类,但由于您在View中不需要event包,因此导入是有意义的只导入你真正需要的东西。即使swingevent包有些相关,也不需要导入事件。

因此,当您使用Java导入内容时,您要么导入整个包import javax.swing.*;包含与包有关的所有类,要么导入包的单个类import javax.swing.JButton;

您永远不会导入包含所有子包及其子包等的包。因为您很可能不需要所有包。

答案 1 :(得分:1)

是的,您需要为每个包进行通配符导入。

为什么呢?就JLS而言,“com.example”和“com.example.pkg”是不相关的包。 JLS中提到了子包的概念,但没有相关的语义。特别是不在“访问”规则中。 JLS 7.1说:

  

“包的分层命名结构旨在方便以常规方式组织相关包,但除了禁止包含具有与之相同的简单名称的子包之外,它本身没有意义。在该包中声明的顶级类型(第7.6节)。

     

例如,名为oliver的包与另一个名为oliver.twist的包之间或名为evelyn.woodevelyn.waugh的包之间没有特殊的访问关系。也就是说,名为oliver.twist的包中的代码无法更好地访问包oliver中声明的类型,而不是任何其他包中的代码。“

(一个允许导入大量无关包的结构会产生不良后果......见下文。)

但为什么?因为这是设计语言的方式。

但是为什么?你需要向Java语言设计团队询问他们在20世纪90年代早期做出设计决策时的想法。


但也许我们可以看到如果有多包通配符导入将会发生什么。

考虑这个包结构,这是一种非常常见的模式:

  com.example.weazellib - contains the public API classes for the library
  com.example.weazellib.impl - contains implementation classes that 
                               shouldn't be used by external clients

众所周知,程序员很懒(很多都好),所以有些程序员可能写这个:

  import com.example.weazellib.**    // hypothetical syntax

他/她现在将拥有此类名称空间中的外部API类和内部类,并且很容易意外地创建对内部的依赖。

(之前你说“使内部类包私有” ...这不起作用。com.example.weazellib中的类需要能够使用{中的类{1}}。如果后者是包私有,那么前者将无法使用它们。)

相比之下,在Java没有导入包“树”的通配符的世界中,你不能意外地 。您必须故意导入com.example.weazellib.impl包。这是 A GOOD THING ,并且比为多个包编写通配符导入的“不方便”重要得多。


另一个问题是通配符导入不利于长期源代码稳定性,超级通配符会使其变得更糟。

假设程序员决定在他的代码中导入implcom.example.weazellib是正确的事情......并使用超级通配符导入两者。并且假设他编写了他的代码以使用com.example.weazellib.impl ...作为com.example.weazellib.impl.ToesImpl

现在考虑如果“weazellib”开发人员添加第三个包ToesImpl包含其他实现类的情况会发生什么...与com.example.weazellib.impl2中的类具有相同的简单名称;例如我们现在有类:

impl

会发生什么?那么现在程序员代码中有一个编译错误。 com.example.weazellib.impl.ToesImpl com.example.weazellib.impl2.ToesImpl 含糊不清...... 因为超级通配符导入的影响从以前没有的包中提取类名。

请注意,常规通配符导入存在同样的问题。这就是很多人不使用通配符导入的原因。但毫无疑问,超级通配符会让问题变得更糟。

答案 2 :(得分:0)

在规范中定义了导入的工作原理。

请参阅Java Language Spec

原因是javax.servlet和javax.servlet.http是不同的包,而import *只引入包成员。

此外,通配符导入不是一个好主意,因为它会降低代码的可读性。