请考虑以下导入语句:为什么要定义多个导入?
import java.io. *; //有意义
import javax.servlet。*;
import javax.servlet.http。*;
是不是像我们已经包含“import javax.servlet。;”因此它会自动包含另一个导入语句,即“import javax.servlet.http。;”?
为什么“import javax.servlet.http。*”为http明确定义?
请澄清,让我知道如果我错了。
请考虑以下导入语句:为什么要定义多个导入?
import java.io. *; //有意义
import javax.servlet。*;
import javax.servlet.http。*;
是不是像我们已经包含“import javax.servlet。;”因此它会自动包含另一个导入语句,即“import javax.servlet.http。;”?
为什么“import javax.servlet.http。*”为http明确定义?
请澄清,让我知道如果我错了。
是的,你需要为每个包做一个通配符导入。
为什么?就JLS而言,“com.example”和“com.example.pkg”是不相关的包。 JLS中提到了子包的概念,但没有相关的语义。特别是不在“访问”规则中。 JLS 7.1说:
“为包装层次命名结构是为了便于以传统方式举办相关的软件包,但本身不是对具有相同的子包一包,禁止其他没有意义简单的名称作为顶级类型(第7.6节)在包声明。
例如,有一个名为
oliver
包和命名oliver.twist
,或命名为evelyn.wood
和evelyn.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.weazellib
和com.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
是不明确的...... ,因为超级通配符导入从一个以前不存在的包中取得类名的影响。
请注意,常规通配符导入存在同样的问题。这就是为什么很多人不使用通配符导入。但毫无疑问,超级通配符会使问题变得更糟。
否当您导入某个导入的内容时,只导入特定的类或导入包以及属于该包的所有类,但不包含属于该包的子包的类。
每个软件包包含一些相关的类和子软件包。子包中的类不一定与父包中的类相关。因此,导入这些也没有意义。这样可以避免不必要的进口并保持项目清洁。
例子:
比方说,你正在为你的GUI应用程序视图类,你可能要分开的担忧,所以你会在你的浏览JComponents
和你Listeners
在你的控制器。
因此,在你查看你会导入:import javax.swing.*;
这样你会得到所有的JComponent
类,但因为你不需要event
包您查看它是有道理的,只导入导入你的实际需要。即使是swing
和event
包有点相关,也不需要导入事件。
所以,当你在Java中导入的东西,你要么导入整个包import javax.swing.*;
随着社会各界关心的软件包,或者导入一个类的包中的类import javax.swing.JButton;
你永远不会与它的所有导入包子程序包及其子程序包等。因为它很可能不需要所有的程序包。
它在规范中定义了导入如何工作。
的原因是和javax.servlet.http是不同的包,并导入*仅在包中的成员带来的。
此外,它不是一个好的主意,通配符导入,因为它使代码不易读。
那么它真的很有意义,为什么你要导入整个“子包”的树,如果你不会使用它们。 – 2013-04-07 00:24:30
@kellax - 我无法弄清楚*你说什么“有道理”。当前的模型,或带有“超级通配符”导入的模型。我的观点是,懒惰的程序员会使用超级通配符而不会思考......'因为它不那么简单。 (就像在Java没有检查异常的情况下他们会忽略异常处理一样)。而且,面对图书馆INTERNAL细节变化的稳定性也存在问题。 – 2013-04-07 00:32:24
感谢您的回复家伙,但是有没有官方的java文档明确表示,子包的存在就像@ kellax提到的一样? – Adarsh 2013-04-07 00:36:05