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内部有一个名为 的静态类InnerOptional此外,它声明了类( static Optional Inner = new Optional();)的一个对象(静态)

这个对象和类名(在 class 内Outer)是相同的,即Inner. 程序显示Optional。预计会显示其中的唯一表达式Outer.Inner.obj,但事实并非如此。然而,实际输出是类的情况。main()InnerOptionalOptional

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

static Optional Inner1 = new Optional();

从它显示的输出来看,似乎对象名称(或变量)被选择而不是类型名称(类Inner),因为它们具有相同的名称。这里应用了什么确切的案例?

4

3 回答 3

14

Java 语言规范的第 6.4.2 段有一些关于在这种情况下适用的规则的信息。

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

这指的是第6.5 段确定名称的含义,其中详细解释了规则。

在您的示例中,Outer.Inner可以引用名为的嵌套类的类型Inner或静态成员变量Inner。规则说变量将被选择而不是类型。

于 2012-10-17T09:47:04.767 回答
3

实际上类名是Outer$Inner。

内部类本质上是 Java 1.1 中引入的一种 hack。JVM 实际上并没有任何内部类的概念,因此编译器不得不拒绝它。编译器在 class 的“外部”生成 B A在同一个中,然后将合成 访问器/构造器添加到它以允许A访问它。

查看以下帖子:

Java 内部类可见性难题

于 2012-10-17T09:35:03.797 回答
2

想想内部类其实已经有了自己的.java文件。这将使您清楚为什么它选择变量而不是 Inner 类。

于 2012-10-17T09:39:40.083 回答