【问题标题】:implemention of imports进口的实施
【发布时间】:2009-05-13 08:43:03
【问题描述】:

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

假设你有一个文件,在这个文件中你有你的 main 函数,你还定义了一个类 Foo,现在 Foo 的不同实现也存在于包裹。假设你想在你的功能中使用这两个版本。

您不能从它的包中显式导入 Foo,即 import mypackage.Foo;

由于这会导致与文件中本地定义的类发生冲突,所以在编译时会产生错误。

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

这将起作用,您可以使用完全限定名称访问 Foo,使用简单名称将导致使用本地 Foo。 我看到的不一致之处在于,虽然前者会产生错误(您已经导入了一个类,并且导入的唯一目的是能够使用简单名称而不是完全限定名称),但后者甚至不会导致警告.

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

所以我的问题是:以这种方式实现它是否有根本原因?

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

【问题讨论】:

  • 小提示:import 语句只被使用,所以你不必输入包名,它什么也不做,它只是一个快捷方式。如果您始终使用完全限定名称,则根本不需要导入。
  • 我理解为什么存在包,只是能够引用导入包中的类并且根本没有警告似乎不一致 - 无论是否在本地定义了具有该名称的类或没有 - 当您显式尝试导入与本地定义的同名的类时,仍然会出现错误。在这两种情况下,该类的 import 语句都是多余的,但一个产生和错误,另一个什么也不做。

标签: java import implementation


【解决方案1】:

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

关于警告:我想没有什么危险的事情发生。你没有使用任何模棱两可的东西。

【讨论】:

  • 在后一个示例中,本地定义的类更具有静默偏好 - 您会期望前一个示例的行为与此一致,因为在这两种情况下导入都是多余的。
  • 如果有关于未使用/冗余导入的警告,所有编译都会突然出现数百个警告。而且,现在没有人手写导入。
  • 未使用和冗余并不是一回事。在很多情况下,您导入的包中包含与本地定义的类之一同名的类?
  • 要点是两种方式都试图达到相同的结果,实际上它们应该。
【解决方案2】:

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

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

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

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

【讨论】:

  • JVM 对导入什么都不做;在内部,它总是使用完全限定的类名。导入仅与编译器相关。
  • Imports 主要与开发人员相关,因为通过导入一个类,您可以通过它的短名称来引用它,而无需自己输入。
  • 有什么理由他们不应该导致相同的行为吗?
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2011-06-05
      • 1970-01-01
      • 2011-04-15
      • 2023-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-21
      • 1970-01-01
      相关资源
      最近更新 更多