Java 为什么可以导入与嵌套类同名的类?
考虑以下代码:Java 为什么可以导入与嵌套类同名的类?,java,language-specifications,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. } } 这段代码编译得很好;但是如果您在Demo中引用Calendar,那么您指的是Demo.Calend
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.
}
}
这段代码编译得很好;但是如果您在Demo
中引用Calendar
,那么您指的是Demo.Calendar
,而不是java.util.Calendar
进口显然是多余的;但是,考虑到不允许您导入与在同一编译单元(per)中定义的顶级类具有相同简单名称的类,允许这样做似乎很奇怪:
第一个代码示例中的这种导入不会是编译时错误,这有什么实际原因吗?我能想到的唯一情况是,您有一个两次(或更多)嵌套的类,其名称与导入相同:
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();
}
}
在这种情况下,嵌套的日历
在嵌套的
类的范围之外不会自动可见,因此导入的日历
类在外部使用,例如在使用导入的
方法中
我不会真的把它描述为一个“实际”的用法,尽管-它只是简单地混淆了在每个上下文中使用的是什么,并且绝对值得避免。不过,我仍然对这个案子的存在感兴趣
我想还有另一个类似的例子:
import java.util.Calendar;
class Demo {
static void useImported() { ... }
}
class Demo2 {
class Calendar {}
static void useNested() { ... }
}
(这些类位于同一编译单元中)。基本上与上面的想法相同。我想,如果导入一个类,它在编译单元的全局空间中是可见的。但是,如果将编译单元或顶级类命名为与导入相同的名称,则基本上是将其与导入相冲突,因此JVM不清楚哪个是哪个。由于它编译了一个类,它将为导入提供一个错误 另外,当它在另一个类中时,您将在那里跟踪导入。它与全局/类级变量和方法级变量相似,如果使用相同的名称定义,则隐藏它们
希望这能有所帮助。“因此JVM会有歧义”这不是歧义,您只是不能引用导入的类,所以它被阻止了。这就像防止类似于
“instanceof Integer
”这样的事情:这对JVM来说并不含糊不清,它可能只是指示程序员错误。@AndyTurner-我解释的是假设JVM允许在同一编译单元中导入和顶级类名相同。对不起,也许我不清楚。是的,我明白这一点,我是说它不是含糊不清的:它是冗余的,就像“instanceof Integer
是一种冗余的写入false
的方式,因此编译器不允许它。它不是冗余的;这是无效的。话虽如此,我很确定这是合法的,因为语言规范没有禁止它。可能这是语言设计者没有考虑的情况。你误读了JLS。它并不禁止导入与顶级类相同的名称,如果“编译单元还声明了一个简单名称为n
”的顶级[sic]类型,则它禁止导入名称。“这不是你所表现出来的情况。”勒布洛赫我不明白你所指出的区别。请您提供一个例子来说明这种区别?在您的例子中,顶级类的名称是什么?它是日历
还是其他什么东西,比如说,演示
?“我很惊讶规范中没有规定第一个案例将被禁止。”;这是一种心理反应。唯一的冲突是导入的简单名称与编译单元中顶级类的名称匹配。区别在于,它只在命名冲突的顶级类的定义中禁止这样做。类完全可以自由地导入与编译单元中的某个顶级类相同的名称。所以Demo
可以导入Calendar
很好。
import java.util.Calendar;
class Demo {
static void useImported() { ... }
}
class Demo2 {
class Calendar {}
static void useNested() { ... }
}