2013-04-06 61 views
0

请考虑以下导入语句:为什么要定义多个导入?

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

import javax.servlet。*;

import javax.servlet.http。*;

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

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

请澄清,让我知道如果我错了。

回答

1

是的,你需要为每个包做一个通配符导入。

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

“为包装层次命名结构是为了便于以传统方式举办相关的软件包,但本身不是对具有相同的子包一包,禁止其他没有意义简单的名称作为顶级类型(第7.6节)在包声明。

例如,有一个名为oliver包和命名oliver.twist,或命名为evelyn.woodevelyn.waugh包之间的另一个包之间没有特殊的调用关系。也就是说,a中的代码名为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 

这是一个众所周知的事实,程序员是懒惰(OK很多都是),所以有些程序员可能会这样写:

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

他/她现在有两个外部API类和内部类在这一类的命名空间,这将是很容易意外上创建内部的依赖。

(你说之前“使内部类的包私人” ...这是行不通的。有迹象表明,需要在com.example.weazellib.impl能够利用班班com.example.weazellib。如果是后者是包私有的,那么前者将无法使用它们。)

相比之下,在Java没有导入包“树”的通配符的世界中,您不能那么做意外。你必须刻意进口impl包。这是一个好东西,比为多个包编写通配符导入的“不方便”更重要。


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

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

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

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

会发生什么?那么现在程序员的代码中就有一个编译错误。 ToesImpl是不明确的...... ,因为超级通配符导入从一个以前不存在的包中取得类名的影响。

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

+0

那么它真的很有意义,为什么你要导入整个“子包”的树,如果你不会使用它们。 – 2013-04-07 00:24:30

+0

@kellax - 我无法弄清楚*你说什么“有道理”。当前的模型,或带有“超级通配符”导入的模型。我的观点是,懒惰的程序员会使用超级通配符而不会思考......'因为它不那么简单。 (就像在Java没有检查异常的情况下他们会忽略异常处理一样)。而且,面对图书馆INTERNAL细节变化的稳定性也存在问题。 – 2013-04-07 00:32:24

+0

感谢您的回复家伙,但是有没有官方的java文档明确表示,子包的存在就像@ kellax提到的一样? – Adarsh 2013-04-07 00:36:05

1

否当您导入某个导入的内容时,只导入特定的类或导入包以及属于该包的所有类,但不包含属于该包的子包的类。

每个软件包包含一些相关的类和子软件包。子包中的类不一定与父包中的类相关。因此,导入这些也没有意义。这样可以避免不必要的进口并保持项目清洁。

例子:
比方说,你正在为你的GUI应用程序视图类,你可能要分开的担忧,所以你会在你的浏览JComponents和你Listeners在你的控制器。

因此,在你查看你会导入:import javax.swing.*;这样你会得到所有的JComponent类,但因为你不需要event包您查看它是有道理的,只导入导入你的实际需要。即使是swingevent包有点相关,也不需要导入事件。

所以,当你在Java中导入的东西,你要么导入整个包import javax.swing.*;随着社会各界关心的软件包,或者导入一个类的包中的类import javax.swing.JButton;

你永远不会与它的所有导入包子程序包及其子程序包等。因为它很可能不需要所有的程序包。

0

它在规范中定义了导入如何工作。

Java Language Spec

的原因是和javax.servlet.http是不同的包,并导入*仅在包中的成员带来的。

此外,它不是一个好的主意,通配符导入,因为它使代码不易读。

相关问题