32

我们知道可以使用外部类的实例来访问非静态内部类,因此静态方法在非静态类内部意义不大。但是从 Java 16 开始,在非静态内部类中允许使用静态方法。

为什么这个限制首先存在?为什么新版本允许这样做?

public class OuterClass {

    class InnerClass {
        static void printMe() {
            System.out.println("Inside inner class");
        }
    }

    public static void main(String[] args) {
        InnerClass.printMe();
    }

}
4

2 回答 2

35

您要求对 Java 16 中的更改进行推理,因此您应该首先检查发行说明,看看它是否有什么要说的。它确实:

JEP 395:记录 ( JDK-8246771 )
tools/javac
记录已添加到 Java 语言中。记录是 Java 语言中的一种新类。它们充当不可变数据的透明载体,其仪式性比普通类少。

自从嵌套类首次被引入 Java 以来,除了由常量表达式初始化的静态 final 字段外,内部的嵌套类声明已被禁止声明静态成员。此限制适用于非静态成员类、本地类和匿名类。

JEP 384: Records (Second Preview)添加了对本地接口、枚举类和记录类的支持,所有这些都是静态定义。这是一个广受欢迎的增强功能,允许将某些声明的范围缩小到本地上下文的编码样式。

虽然JEP 384允许静态本地类和接口,但它并没有放松对静态成员类和内部类接口的限制。内部类可以在其方法体之一内声明静态接口,但不能作为类成员。

作为自然的下一步,JEP 395进一步放宽了嵌套限制,并允许在内部类中声明静态类、方法、字段等。

有关详细信息,请参阅JEP 395

于 2021-07-25T18:16:57.873 回答
25

具体推理在JEP 395中给出

内部类的静态成员

如果内部类声明显式或隐式静态成员,则当前指定为编译时错误,除非该成员是常量变量。这意味着,例如,内部类不能声明记录类成员,因为嵌套的记录类是隐式静态的。

我们放宽了这个限制,以便允许内部类声明显式或隐式静态的成员。特别是,这允许内部类声明一个作为记录类的静态成员。

换句话说,有必要针对特定​​情况取消对内部类静态成员的限制;即允许record在内部类中声明类。但他们决定借此机会取消所有情况下的限制。

这意味着设计者已经得出结论,由于技术原因,整个原始限制既不是必要的,也不是可取的。


为什么这个限制首先存在?

这是一个更难的问题。做出这种限制的决定是在 1996 年或 1997 年初设计 Java 1.1 时做出的。任何人都不太可能仍然准确地记住最初决定背后的原因。因此,除非有人能找到同时代的书面资料,否则我们永远无法确定。

(Brian Goetz 在上面评论说:“......在添加嵌套时(Java 1.1),在另一个类中有多种可能的静态解释,所以这个问题被推迟了。”这当然是有道理的,但这可能是(只是)一个人对大约 25 年前发生的事情的回忆。如果是我,我不会对我从那时起的记忆有信心。除非我有同时期的会议记录、笔记等可供参考。)

这里有一些关于原始限制的理由的猜测:

于 2021-07-26T03:18:31.477 回答