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

带有静态内部类的Java新关键字,java,class,static,new-operator,Java,Class,Static,New Operator,我知道以前有人问过这个问题,但大部分都是关于某个图书馆的。而给出的答案并没有真正向我解释发生了什么 这就是为什么我在这里设置了一个非常简单的测试场景,并试图处理它,但仍然有一些问号! 简单代码由两个文件组成: Main.java public class Main { public static void main(String[] args) { // this works, and inner1 and inner2 seem to be new instances

我知道以前有人问过这个问题,但大部分都是关于某个图书馆的。而给出的答案并没有真正向我解释发生了什么

这就是为什么我在这里设置了一个非常简单的测试场景,并试图处理它,但仍然有一些问号!

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

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();
    }
}
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");
        }
    }
}
Outer.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();
    }
}
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");
        }
    }
}
因此,似乎即使
internal
类是用static声明的,我们还是创建了两个名为inner1和inner2的新实例。那为什么叫静态呢

反过来,如果我删除static,如
InnerNoStatic
中所述,我将如何获取该类的实例

因此,看起来即使内部类是用static声明的,我们还是创建了两个名为inner1和inner2的新实例。那为什么叫静态呢

与非“静态”内部类相反,“静态”内部类的对象不绑定到其封闭类的对象。拥有一个“静态”的内部类而不是将该类移动到“顶层”是一种向用户发出信号的便捷方式,表明该内部类的对象与外部类没有太多的用途,类似于e。g<代码>地图条目

反过来,如果我像InnerNoStatic那样删除了static,我将如何获取该类的实例

比如说

public class Outer {

  private InnerNoStatic innerNoStatic = new InnerNoStatic();

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

因此,看起来即使内部类是用static声明的,我们还是创建了两个名为inner1和inner2的新实例。那为什么叫静态呢

static
意味着嵌套类更加独立。它主要是为了提高封装性、可读性和可维护性而设计的,它是对类进行逻辑分组的好方法

反过来,如果我像InnerNoStatic那样删除了static,我将如何获取该类的实例

语法有点不同,因为您需要
Outer
的实例

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

static
这里说明了如何将
internal
InnerNoStatic
用于
Outer

Outer.InnerNoStatic inner3 = new Outer(). new InnerNoStatic();
因为
内部
外部
中是静态的,所以它不绑定到
外部
的任何特定实例(与往常一样,静态成员属于该类,而不属于该类的任何特定实例)。这就解释了它是如何编译的:

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
对象)



注意:很容易混淆
newouter.Inner()带有
新的外部()。它们做的不是同一件事(前者中的“Outer”基本上扮演名称空间的角色,而后者中的
newouter()
创建一个
Outer
对象)。也就是说,在前者中有一个构造函数调用(
internal()
),但在后者中有两个构造函数调用(
Outer()
internal()
)。

非静态内部类始终引用相应的外部类。因此,这样的类只能由外部类实例化


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

请检查,谢谢,这是一个非常好的补充,我没有无意中发现!