自动导入包的顺序和歧义

时间:2014-01-31 10:31:00

标签: java import jls

JLS: Chapter 7. Packages:

  

包由许多编译单元组成(第7.3节)。编译单元自动访问其包中声明的所有类型,并且自动导入预定义包java.lang 中声明的所有公共类型。

让我们假设以下代码:

package com.example.p1;
public class MyClass { }
package com.example;
public class MyClass { }
package com.example;
public class String { }
package com.example;

import com.example.p1.*;

public class MainNameClash {
   private String s;    // No Error, even though ambiguous with java.lang.String!
   private MyClass m;   // No error, even though ambiguous with com.example.p1.MyClass!
}

如果我将MyClasscom.example移到com.example.p2并将其导入import com.example.p2.*,我会在Error: the type MyClass is ambigious处使用java.lang

看起来包中的Types总是优先于任何其他导入的类型,无论是从{{1}}自动还是显式地使用通配符导入,并且编译器不会发出任何警告或错误

问题:

  • 为什么java编译器在这种情况下不会发出歧义错误?
  • JLS中定义了哪种行为?

3 个答案:

答案 0 :(得分:7)

表格的导入声明:

import packageName.subPackage.*

Type-Import-on-Demand Declarations。即,只有在当前编译单元范围内没有该类型时,才会导入类或其中的任何类型。

仅来自该JLS部分的示例 7.5.2-1

  

声明可能被简单名称为Vector的类型的单一类型导入声明遮蔽; 由名为Vector的类型并在编译单元所属的包中声明;或任何嵌套的类或接口。

因此,如果您的课程与同一个课程中有String课程,那么在该课程中使用String会引用您的课程,因为java.lang.String将不会被导入。它只会在需求上导入,如example 6.4.1-2JLS § 6.4.1 - Shadowing所示。

答案 1 :(得分:2)

我认为Shadowing & Obscuring涵盖了这一点,因为包范围的Class优先于通配符导入。

答案 2 :(得分:0)

实际上问题是关于简单类型名称

  

6.5.5.1 简单类型名称如果类型名称由单个标识符组成,则标识符必须在一个范围内   使用此

显示类型的可见声明

关于范围,我们可以在这里阅读:

  

6.3)声明的范围是程序的范围   声明声明的实体可以使用a来引用   简单名称,只要它是可见的

...

  

单一类型导入声明导入的类型的范围   (§7.5.1)或类型 - 按需进口声明(§7.5.2)就是全部   编译单元中的类和接口类型声明(第7.6节)   导入声明出现在其中,以及任何注释   编译单元的包声明(如果有的话)。