9

record这让我感到意外:即使它现在已成为关键字,我也能够使用该名称声明一个变量。看看这个:

public class Main {
    
    static class Foo {
        void bar() { System.out.println("Foo.bar"); }
    }
    
    record R (int a) {}
    
    public static void main(String[] args) {
        Foo record = new Foo();
        record.bar();
        
        R r = new R(5);
        System.out.println(r);
    }
}

当使用 Java 17 编译和运行时,这会给出:

Foo.bar
R[a=5]

我曾预计这会导致错误,就像尝试声明名为class. 正如我认识的 Java 人一样,他们非常小心地不破坏现有代码,所以我认为这可能是一个深思熟虑的选择。

(你甚至不能声明一个名为的变量const,因为它const Java 中的一个关键字。)

4

2 回答 2

10

是的,这是合法的,因为record它不是保留关键字;它只是一个上下文关键字。

Java 语言规范从 Java 9 开始区分上下文关键字(最初是“受限关键字”和后来的“受限标识符”)和保留关键字,因为该版本中引入了几个新关键字。JLS 9 ( §3.9 ) 中给出了基本原理:

另外十个字符序列是受限关键字:open, module, requires, transitive, exports, opens, to, uses, provides, 和with. 这些字符序列被标记为关键字,仅在它们作为终端出现的地方ModuleDeclarationModuleDirective产生式(第 7.7 节)。它们在其他任何地方都被标记为标识符,以便与 Java SE 9 之前编写的程序兼容。

本质上,Foo record = new Foo();它在 Java 17 中必须是合法的,因为它在早期版本中是合法的,当时record它不是任何类型的关键字,并且向后兼容性是 Java 语言新版本的一个非常高的优先级。

于 2021-11-12T15:27:28.560 回答
6

好的,当再次在 JLS 中查找时const,我看到这record是一个上下文关键字,而const只是一个关键字。上下文关键字是根据上下文进行解析的,当解析器确定它没有查看记录声明时,它不会抱怨。

于 2021-11-12T15:01:21.837 回答