Java 带有静态内部的新关键字 class

Java new keyword with static inner class

我知道以前有人问过这个问题,但大多是针对某个库的。给出的答案并没有真正向我解释发生了什么。

这就是为什么我在这里设置了一个非常简单的测试场景,并尝试 fiddle 用它,但仍然有一些问号! Online Java Example

简单代码由两个文件组成:

Main.java

public class Main
{
    public static void main(String[] args) {
        // this works, and inner1 and inner2 seem to be new instances
        Outer.Inner inner1 = new Outer.Inner();
        Outer.Inner inner2 = new Outer.Inner();
        inner1.setName("Mario");
        inner1.say();
        inner2.setName("Luigi");
        inner2.say();

        // if Inner is not a public static class this gives this error:
        // error: an enclosing instance that contains Outer.InnerNoStatic is required
        Outer.InnerNoStatic inner3 = new Outer.InnerNoStatic();
    }
}

Outer.java

public class Outer {
    public static class Inner {
        private String name;

        public void say() {
            System.out.println("Hi " + name);
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public class InnerNoStatic {
        public void say() {
            System.out.println("Hi from InnerNoStatic");
        }
    }
}

所以看起来即使 Inner class 是用静态声明的,我们还是创建了两个新实例,分别称为 inner1 和 inner2。那为什么叫static呢?

反过来,如果我删除静态变量,如 InnerNoStatic 中那样,我将如何获取该 class 的实例?

So it seems like even though the Inner class is declared with static, we create two new instances called inner1 and inner2. Why is it called static then?

"static" 内部 class 的对象不依赖于其封闭 class 的对象,这与非 "static" 内部 class 的对象相反。拥有一个 "static" 内部 class 而不是将 class 移动到 "top level" 是一种向用户发出信号的便捷方式,表明该内部 class 的对象还没有与外部 class 分开使用,类似于 e。 G。 Map.Entry

And in turn, if I remove the static, as in InnerNoStatic how would I go about getting an instance of that class?

例如

public class Outer {

  private InnerNoStatic innerNoStatic = new InnerNoStatic();

  public InnerNoStatic getInnerNoStatic () {
    return innerNoStatic;
  }
  // ...

Outer.InnerNoStatic innerNoStatic = new Outer().getInnerNoStatic();

So it seems like even though the Inner class is declared with static, we create two new instances called inner1 and inner2. Why is it called static then?

static 意味着嵌套的 class 更独立。它的设计主要是为了提高封装性、可读性和可维护性,并且它是逻辑分组 classes 的好方法。

And in turn, if I remove the static, as in InnerNoStatic how would I go about getting an instance of that class?

语法有点不同,因为您需要 Outer.

的实例
Outer.InnerNoStatic inner3 = new Outer(). new InnerNoStatic();

static 此处指示如何使用 InnerInnerNoStatic 相对于 Outer.

因为 InnerOuter 中是静态的,它不依赖于 Outer 的任何特定实例(一如既往,静态成员属于 class,不是那个 class 的任何特定实例)。这解释了它是如何编译的:

Outer.Inner inner1 = new Outer.Inner();
然而,

InnerNoStatic 是一个实例成员(也就是说:如果它不是静态的,它就绑定到给定的成员)。这解释了为什么编译器会在此处引发错误:

Outer.InnerNoStatic inner3 = new Outer.InnerNoStatic();

因为InnerNoStatic必须绑定到Outer的实例,所以需要使用这样的实例来创建inner3:

Outer.InnerNoStatic inner3 = new Outer().new InnerNoStatic(); //note the calls

您也可以使用现有实例。

Outer outer = new Outer();
Outer.InnerNoStatic inner3 = outer.new InnerNoStatic();

在这两种情况下,Outer 实例用于构建 InnerNoStatic 实例(只是没有变量指向使用 new Outer().new InnerNoStatic() 创建的 Outer 对象)


注意:很容易将 new Outer.Inner();new Outer().new Inner(); 混淆。它们不是在做同样的事情(前者中的 "Outer" 基本上是扮演命名空间的角色,而后者中的 new Outer() 是创建一个 Outer 对象)。也就是说,前者调用一次构造函数(Inner()),而后者调用两次构造函数(Outer()Inner())。

非静态内部 classes 始终具有对相应外部 class 的引用。因此,这样的 class 只能由 Outer class.

实例化

相反,静态内部 class 没有对外部 class 的引用,并且可以由任何其他对象创建,如果可见性允许的话。这与不需要调用对象实例的静态方法的行为非常相似。