0

考虑以下导入语句:

导入java.io.*;// 有道理

导入 javax.servlet.*;

导入 javax.servlet.http.*;

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

为什么为 http 明确定义了“import javax.servlet.http.*”?

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

4

3 回答 3

1

不,当您导入某些内容时,您仅导入特定类或导入包以及属于该包的所有类,而不是属于该包的子包的类。

每个包都包含一些相关的类和子包。子包中的类不一定与父包中的类相关。因此,将它们也导入是没有意义的。这样可以避免不必要的导入并保持项目干净。

示例:
假设您正在为您的 GUI 应用程序构建一个 View 类,您可能希望将关注点分开,以便您JComponents在 View 和ListenersControllers 中拥有关注点。

因此,在您的视图中,您将导入:import javax.swing.*;这样您将获得所有JComponent类,但由于您的视图中不需要event包,因此导入只导入您实际需要的内容是有意义的。即使 thoswingeventpackage 有点相关,也不需要导入事件。

因此,当您在 Java 中导入某些内容时,您要么导入整个包import javax.swing.*;以及与包相关的所有类,要么导入包的单个类import javax.swing.JButton;

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

于 2013-04-06T23:57:11.253 回答
1

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

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

“包的分层命名结构旨在方便以常规方式组织相关包,但除了禁止包具有与顶级类型相同的简单名称的子包(§7.6 ) 在该包中声明。

例如,一个包名oliver和另一个包名oliver.twist之间,或者包名evelyn.wood和包之间没有特殊的访问关系evelyn.waugh。也就是说,一个名为的包中的代码对包oliver.twist中声明的类型的访问并不oliver比任何其他包中的代码更好。”

(并且允许导入许多不相关的包的结构会产生不良后果……见下文。)

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

但为什么?您需要询问 Java 语言设计团队,他们在 1990 年代初期做出设计决策时的想法是什么。


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

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

  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需要能够使用中的类com.example.weazellib.impl。如果后者是包私有的,那么前者将无法使用它们。)

相比之下,在 Java 没有导入包“树”的通配符的世界中,您不能意外地这样做。您必须故意导入impl包。这是一件好事,而且比为多个包编写通配符导入的“不便”重要得多。


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

假设一个程序员决定在他的代码中同时导入com.example.weazellibcom.example.weazellib.impl是正确的做法......并使用超级通配符来导入两者。并假设他编写代码以使用com.example.weazellib.impl.ToesImpl... as ToesImpl

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

com.example.weazellib.impl.ToesImpl
com.example.weazellib.impl2.ToesImpl

发生什么了?好吧,现在程序员代码中有一个编译错误。 ToesImpl是模棱两可的......因为超级通配符导入从以前不存在的包中提取类名的影响。

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

于 2013-04-07T00:22:08.713 回答
0

它在规范中定义了导入的工作方式。

请参阅Java 语言规范

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

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

于 2013-04-07T00:01:02.077 回答