为什么可以导入与嵌套类同名的类?

时间:2017-04-06 14:51:52

标签: java language-specifications

请考虑以下代码:

import java.util.Calendar;

class Demo
{
    class Calendar {}

    public static void main (String[] args) {
      // System.out.println(Calendar.DAY_OF_WEEK);  // Would be an error.
    }
}

此代码编译良好;但如果您在Calendar中引用Demo,则表示Demo.Calendar,而非java.util.Calendar

进口显然是多余的;但是考虑到你不允许导入一个与同一编译单元中定义的顶级类相同的简单名称的类(JLS Sec 7.5.1),这似乎很奇怪:

import java.util.Calendar;  // error: Calendar is already defined in this compilation unit

class Calendar {}

是否有一个实际的原因可以解释为什么第一个代码示例中的导入不会是编译时错误?

2 个答案:

答案 0 :(得分:3)

我能想到的唯一一个案例是你有一个两次(或更多)的类,与导入的名称相同:

import java.util.Calendar;

class Demo {
  static class Nested {
    static class Calendar {}

    static void useNested() {
      System.out.println(Calendar.class);  // Demo.Nested.Calendar
    }
  }

  static void useImported() {
    System.out.println(Calendar.class);  // java.util.Calendar
  }

  public static void main(String[] args) {
    Nested.useNested();
    useImported();
  }
}

Ideone demo

在这种情况下,嵌套的Calendar不会在Nested类的范围之外自动显示,因此导入的Calendar类在外部使用,例如在useImported方法中。

我不会将此描述为"实用"但是,使用它 - 在每种情况下使用哪一种都很简单,绝对值得避免。尽管如此,我仍然感兴趣的是这个案例。

我想还有另一个类似的案例:

import java.util.Calendar;

class Demo {
  static void useImported() { ... }
}

class Demo2 {
  class Calendar {}

  static void useNested() { ... }
}

(这些类在同一个编译单元中)。基本上与上面的想法相同。

答案 1 :(得分:0)

我想,如果你导入一个类,它在该编译单元的全局空间中是可见的。但是,如果您将编译单元或顶级类命名为与导入相同,那么您基本上与导入进行冲突,因此JVM知道哪个是哪个是不明确的。并且由于它编译了一个类,它将导致导入错误。

此外,当它在另一个类中时,你正在影响那里的导入。它与全局/类级别变量和方法级别变量的方式类似,如果使用相同名称定义则隐藏它们。

希望这有帮助。