使用 `record` 作为变量名是否合法,即使它是关键字?

Is it legal to use `record` as a variable name even though it's a keyword?

这让我感到惊讶:我能够声明一个名称为 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 的变量,因为 Java 中的 const is a keyword。)

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

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

由于引入了几个新关键字,Java 语言规范区分了上下文关键字(最初是“受限关键字”和后来的“受限标识符”)和自 Java9 以来的保留关键字在那个版本中。基本原理在 JLS 9 (§3.9):

中给出

A further ten character sequences are restricted keywords: open, module, requires, transitive, exports, opens, to, uses, provides, and with. These character sequences are tokenized as keywords solely where they appear as terminals in the ModuleDeclaration and ModuleDirective productions (§7.7). They are tokenized as identifiers everywhere else, for compatibility with programs written prior to Java SE 9.

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