实施进口

时间:2009-05-13 08:43:03

标签: java import implementation

首先,我不是一个Java人,但是我发现表面上出现的与导入工作方式不一致的东西。

假设您有一个文件,并且在此文件中您拥有主要功能,并且您还定义了一个类 Foo ,现在 Foo 的另一个实现也存在于包。假设您要在功能中使用这两个版本。

您无法从其软件包中明确导入 Foo ,即 import mypackage.Foo;

因为这会导致与文件中本地定义的类冲突,所以在编译时会生成错误。

可以做的是导入整个包,即 import mypackage。*;

这将有效,您可以使用完全限定名称访问 Foo ,使用简单名称将导致使用本地 Foo 。 我看到的不一致是,前者生成错误(您导入了一个类,导入的唯一目的是能够使用简单名称而不是完全限定名称),后者甚至不会导致警告

我原本以为这两种情况都会产生一个警告,即你可能正在使用错误的类,因为它在2个地方定义,或者import语句是多余的,因为简单名称的使用将解析为本地定义的类,不是进口的。

所以我的问题是:是否存在以这种方式实施的潜在原因?

是的,这是一个异常情况,我明白这一点。

4 个答案:

答案 0 :(得分:9)

即使不导入mypackage,您也可以使用完全限定名称访问Foo。*;

关于警告:我猜,没有什么危险的事情发生。你没有使用任何含糊不清的东西。

答案 1 :(得分:3)

正如上面的回答所说,导入对其他包中的Foo实际上没有任何作用;无论您是否导入,都不能通过短类名引用其他Foo,而可以通过完全限定的类名引用它。

从概念上讲,您可以认为import mypackage.*不一定是“从mypackage导入所有类”,但可能“从mypackage导入所有非冲突类”。我不知道Sun的编译器实现是如何做到的,但它绝对可以决定不将mypackage.Foo作为通配符的一部分进行匹配(因此根本不会导入它),并且代码的工作方式也相同。

导入实际上只是设置从短类名到完全限定类名的别名(例如,当我说Date将其解释为java.util.Date时)。如果您做了一些完全冗余的事情,例如只导入冲突的类,那么可以预期会收到警告。但是,如果您使用*提取整个包,那么编译器抱怨其中一个类名冲突似乎是错误的;这种情况在实践中经常发生,并且在99%以上的时间内无害,它会产生一个“狼嚎狼吞虎咽”的综合症,以至于你不太可能注意到这些和其他警告,因为你只是习惯被他们轰炸。

顺便说一句,如果你同时导入java.util.*java.sql.*,这是允许的,并且本身不会导致任何警告;但是如果你试着只引用Date(在你的本地包中没有这样的类),你会得到一个编译错误,因为名称不明确。

答案 2 :(得分:1)

导入mypackage。*对于mypackage中的所有其他内容可能是必需的。如果有警告,那么根本就很难避免它,即你必须完全限定你在mypackage中使用的所有其他类等。 更糟糕的是,考虑mypackage版本1不包含Foo的情况,因此没有冲突,因此没有理由发出警告。版本2包含Foo,但当然不是您想要在程序中访问的Foo。 因此,如果编译器警告“import package。*”冲突,则会使“import package。*”可能不太向上兼容。

答案 3 :(得分:1)

您可以将“import p。*”视为“当您无法解析当前文件中的名称时,请尝试在包p中解析它”。编译器在它看到import语句时不会导入 p 中的所有内容。相反,当它找到无法在即时编译单元中解析的名称时,它会查找 p (以及在import ... *语句中命名的其他包)。