在Java中使用相同的内部类名和对象名

12
在下面的代码片段中,看起来应该会出现一些编译错误,但实际上并没有:
class Outer {
    public static class Inner {
        static String obj = "Inner";
    }

    static Optional Inner = new Optional();
    //The (inner) class name and the object name are same.
}

class Optional {
    String obj = "Optional";
}

public class Main {

    public static void main(String[] args) {
        System.out.println(Outer.Inner.obj);
        //Refers to the string inside the optional class
    }
}

Outer 内部有一个名为 Inner 的静态类。此外,它声明了一个类 Optional 的对象(静态)(static Optional Inner = new Optional();)

这个对象和类名(在类 Outer 中)是相同的,即 Inner。程序显示 Optional。在 main() 函数中唯一的表达式 Outer.Inner.obj 预期显示 Inner,但实际上没有。而是输出了 Optional,这是因为它是 Optional 类的情况。

一种显示 Inner 的方法是将对象名称更改为其他名称。

static Optional Inner1 = new Optional();
根据输出显示,似乎选择了对象名称(或变量),而不是类型名称(类Inner),因为它们具有相同的名称。这里应用了什么确切情况?
3个回答

14

Java语言规范第6.4.2段提供了关于此情况适用的规则信息。

简单名称可能出现在可能被解释为变量、类型或包的名称的上下文中。在这些情况下,§6.5的规则指定首选选择变量而不是类型,并且首选选择类型而不是包。因此,有时可能无法通过它的简单名称引用可见类型或包声明。我们称这样的声明为模糊

这指的是第6.5节名称的确定,详细解释了规则。

在您的示例中,Outer.Inner 可能指嵌套类Inner的类型,也可能是静态成员变量Inner。规则表明将选择变量而不是类型。


3

实际上,类名是Outer$Inner。

内部类本质上是在Java 1.1中引入的一种技巧。JVM实际上没有任何内部类的概念,因此编译器必须进行处理。编译器在同一个包中生成B"外部"的A,然后添加合成的访问器/构造函数以允许A访问它。

请查看以下帖子:

Java内部类可见性谜题


这确实是一个非常好的答案,针对这里没有被问到的问题。 - LuGo

2

想象一下内部类实际上有自己的 .java 文件。这将使你清楚为什么它选择变量而不是内部类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接