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

2022-09-01 07:27:33

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

为什么一开始就存在这种限制?为什么在较新版本中允许这样做?

public class OuterClass {

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

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

}

答案 1

您要求对Java 16中的更改进行推理,因此您应该首先查看发行说明,看看它是否有任何要说的。它的作用是:

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

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

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

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

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

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


答案 2

具体推理在JEP 395中给出

内部类的静态成员

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

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

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

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


为什么一开始就存在这种限制?

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

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

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


推荐