2017-04-06 84 views
3

考虑下面的代码:为什么你可以导入一个与嵌套类名称相同的类?

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. 
    } 
} 

此代码编译的罚款;但如果你是指CalendarDemo,你是指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 {} 

有为什么像第一个代码示例中那样导入的实际原因不会是编译时错误?

+0

这不是多余的;这是无效的。据说,我很确定这是合法的,因为语言规范并不禁止它。可能这是语言设计者没有考虑的情况。 – davmac

+0

你误读了JLS。它不禁止导入与顶级类相同的名称,如果“编译单元还声明了简单名为'n'的顶级[sic]类型”,则禁止导入名称'n'。这不是你展示的情况。 –

+0

@LewBloch我不明白你指出的区别。请你能举一个例子来证明这个区别吗? –

回答

3

我能想出的唯一情况是,你有一个两次(或更多)-nested具有相同名称的进口类:

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

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

我不会真的形容这是一个“实用”的使用,虽然 - 它只是普通的混乱哪个在每个上下文中使用,绝对值得避免。不过,它仍然让我感兴趣的是这种情况的存在。


我假设有另一个类似的情况:

import java.util.Calendar; 

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

class Demo2 { 
    class Calendar {} 

    static void useNested() { ... } 
} 

(其中这些类在相同的编译单元)。基本上和上面一样。

0

我想,如果导入一个类,它是在编译单元的全球空间可见。但是,如果您将编译单元或顶级类的名称与导入的名称相同,那么您基本上与导入相冲突,因此JVM知道哪个是哪一个是不明确的。并且自从编译一个类以来,它会给导入一个错误。

而且,当它的另一个类中,你那边阴影进口。它与全局/类级别变量和方法级别变量隐藏它们(如果使用相同名称定义的)相似。

希望这会有所帮助。

+0

“,因此它对于JVM来说是模棱两可的。”它并不含糊,你根本无法引用导入的类,因此它被阻止。这就像阻止像“”instanceof Integer“这样的东西:它不是JVM的含糊不清,它可能只是表示程序员错误。 –

+0

@AndyTurner - 我解释了假设JVM是否允许导入和顶级类名在同一编译单元中相同。对不起,也许我不清楚。 –

+0

是的,我明白了,并且我在说它并不含糊:它是*冗余的*,与''“'instanceof Integer'是编写'false'的冗余方式相同,因此编译器不允许。 –

相关问题