关于java:静态嵌套类可以多次实例化吗?

Can a Static Nested Class be Instantiated Multiple Times?

考虑到我对编程的所有其他类型静态特性的了解,我认为答案是"否"。然而,看到像OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();这样的声明让我感到惊讶。


是的,在static嵌套类型的语义中没有任何东西可以阻止您这样做。这段代码运行良好。

1
2
3
4
5
6
7
8
9
public class MultipleNested {
    static class Nested {
    }
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Nested();
        }
    }
}

也见

  • public static interface Map.Entry
    • public static class AbstractMap.SimpleEntry
      • 可能是最著名的嵌套类型。显然是多次实例化的。

现在,当然嵌套类型可以执行自己的实例控制(例如private构造函数、singleton模式等),但这与它是嵌套类型这一事实无关。另外,如果嵌套类型是一个static enum,那么当然您根本无法实例化它。

但是,一般来说,可以多次实例化一个static嵌套类型。

注意,从技术上讲,static嵌套类型不是"内部"类型。

JLS 8.1.3内部类和封闭实例

An inner class is a nested class that is not explicitly or implicitly declared static.

也就是说,根据jls的术语,内部类不是static。如果它是static,那么它只是一个嵌套类型。

那么,static是什么意思?

static只是表示嵌套类型不需要实例化封闭类型的实例。

也见

  • Java内部类和静态嵌套类小精灵
  • JAVA:静态与非静态内部类


@polygenelubricants :
But in general, yes, a static nested
type can be instantiated multiple
times.

为了确保100%的内容,我扩展了您的代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MultipleInner {
    static class Inner {
        private int state;
        public int getState() { return state; }
        public void setState(int state) { this.state = state; }
    }

    public static void main(String[] args) {
        List<Inner> inners = new ArrayList<Inner>();
        for (int i = 0; i < 100; i++) {
            Inner inner = new Inner();
            inner.setState(i);
            inners.add(inner);
        }
        for (Inner inner : inners) {
            System.out.println(inner.getState());
        }
    }
}

当然,结果是:

1
2
3
4
5
6
7
8
9
10
0
1
2
3
.
.
.
97
98
99


这是合法的。内部类是静态的这一事实在这里给了您一个好处;它的实例没有绑定到包含类的任何实例,因此它们可以自由地实例化(只要访问限定符允许)。

但是,代价是内部类不能使用包含类的非静态成员/方法。


静态嵌套类确实是实例——如前所述,它们是顶级类,位于"外部"类的名称空间中,并且遵循与"外部"类的引用相关的静态语义。此代码示例演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class OuterClass {
    String outerStr ="this is the outer class!!" ;
    public static class StaticNestedClass {
        String innerStr ="default / first instance" ;      
    }

    public static void main(String[] args) {
        OuterClass.StaticNestedClass nestedObject1 = new OuterClass.StaticNestedClass();        
        OuterClass.StaticNestedClass nestedObject2 = new OuterClass.StaticNestedClass();
        nestedObject2.innerStr ="second instance" ;
        System.out.println(nestedObject1.innerStr) ;
        System.out.println(nestedObject2.innerStr) ;
    }
}

output:

default / first instance
second instance

内部类可以使用包含类的非静态成员/方法。它只能通过封闭类的对象引用来使用它们-

1
2
3
4
5
6
7
8
9
10
11
12
13
     public class MultipleInner {
      private int outerstate =10;
      static class Inner {
        private int state;
        public int getState() { return state; }
        public void setState(int state) { this.state = state; }
      }

     public static void main(String[] args) {      
        Inner inner = new Inner();
        inner.setState(new MultipleInner().outerstate);
        System.out.println(inner.getState());        
     }

}

因此,内部类不必为无法访问封闭类的非静态成员而付出代价。


是的,你可以随心所欲地多次引用它。

也许你看到这一点的原因,是因为程序考虑在某个地方存储一个引用。尽管我同意你的观点,但这似乎很奇怪:S