关于 class 嵌套在 java 中的查询

A query about class nesting in java

public class Outer{
    public class Inner{
    }
}

public class Main {
    public static void main(String[] args) {
        Outer objOut = new Outer();
        //Outer.Inner object1= objOut.new Inner();  // runes without a problem
        //objOut.Inner object2= objOut.new Inner(); //gives error
    }
}

这听起来有点业余,但是,Outer.InnerobjOut.Inner 之间有什么区别。

两者都不编译。

要使前者编译,应声明一个变量,并给出该变量的名称。

Outer.Inner obj = objOut.new Inner();

即使您执行了这一步,后者也不会编译,因为 objOut.Inner 既不是类型(因为主表达式 objOut 不是类型)也不是有效名称(因为 [= an identifier (jls-3.8) 中不允许使用 14=])。

针对您的情况的简化 rule (jls-14.4)

LocalVariableType VariableDeclaratorId [= VariableInitializer];

这个:

Outer.Inner = objOut.new Inner();

将无法编译,但如果将其更改为:

Outer.Inner object = objOut.new Inner();

将意味着创建一个 inner class 的实例,它引用了 Outer class - objOut 将是 Outer [=48= 的实例].

还有这个:

objOut.Inner = objOut.new Inner();

将无法编译,因为 objOut Outer class 的实例没有属性 Inner

而且 Outer class 知道 Inner class 的实例 - 它是 Inner class 知道的实例创建它的 Outer class 实例。

编辑

行:

objOut.Inner object2= objOut.new Inner();

不会编译,因为 Inner 类型标识符属于 Outer class 而不是此 class 的实例。

您不能将一个变量名用作另一个变量的 类型 ,这正是您要对 objOut.Inner 所做的。变量的类型是Inner(或者可选的Outer.Inner)。

因为 Inner 是一个 inner class,它与其外部 class 的 实例 相关联(它的 包含实例)。当您创建它的实例时,您可以选择¹指定它关联的对象实例,这就是您在 objOut.new Inner.

中所做的

这个例子可能有助于使它更清楚一点:

public class Example {
    private String str;

    public class Inner {
        void show() {
            // Show the string for the Example this Inner is part of
            System.out.println(Example.this.str);
        }
    }

    public Example(String s) {
        this.str = s;
    }

    public static void main(String[] args) {
        Example e1 = new Example("e1");
        Example e2 = new Example("e2");
        Inner i1 = e1.new Inner();
        i1.show(); // "e1"
        Inner i2 = e2.new Inner();
        i2.show(); // "e2"
    } 
}

Live Copy

注意 i1 Inner 实例如何将 e1 作为其封闭的 Example 实例,因此可以看到 e1str , 但是 i2 得到 e2 作为它的封闭实例所以它看到 e2str.

我建议 this Java tutorial 了解更多信息。


¹ 有时它不是可选的,例如在我上面的 Example class 中,因为在使用 new Inner 的地方,没有它可以使用的默认实例。它在 Exampleinstance 方法中是可选的,但在 static 方法中不是。