在Java中使用相同的内部类名和对象名
在下面的代码片段中,可能看起来它应该发出一些编译错误,但它不会:
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
)上选择的,因为它们具有相同的名称。 这里应用了哪些确切的案例?
Java语言规范的第6.4.2段有关于在这种情况下适用的规则的一些信息。
一个简单的名称可能出现在上下文中,它可能被解释为变量,类型或包的名称。 在这些情况下,§6.5的规则指定将优先选择变量而不是类型 ,并且将优先选择类型而不是包。 因此,有时可能无法通过其简单名称引用可见类型或包声明。 我们说这样的声明是模糊的 。
这是指第6.5段确定名称的含义 ,它详细解释了规则。
在您的示例中, Outer.Inner
可以引用名为Inner
的嵌套类的类型,或静态成员变量Inner
。 规则说将在类型上选择变量。
实际上,class级名称是Outer $ Inner。
内部类本质上是Java 1.1中引入的hack。 JVM实际上没有内部类的任何概念,因此编译器必须提出它。 编译器在类 B
“外部”生成类 B
,但是在同一个包中 ,然后向其添加合成 访问器/构造函数以允许A
访问它。
查看以下post:
Java内部可见性难题
想想内部类实际上有自己的.java文件。 这将使您清楚地知道为什么它选择Inner类的变量。