为什么在 Java 16 中的非静态内部类中允许静态方法?

问题描述

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

为什么会存在这个限制?为什么在较新的版本中允许这样做?

public class OuterClass {

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

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

}

解决方法

您要求对 Java 16 中的更改进行推理,因此您应该首先检查 Release Notes 以查看它是否有任何要说的内容。它确实:

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

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

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

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

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

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

,

具体推理见JEP 395

内部类的静态成员

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

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

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

这意味着设计者已经得出结论,最初的限制作为一个整体既不是技术原因也不是可取的。


为什么会有这个限制?

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

这里有一些关于最初限制的理由的猜测: