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

Axe*_*xel 11 java jls java-record java-17

这令人惊讶:我能够用该名称声明一个变量,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Foo.bar
R[a=5]
Run Code Online (Sandbox Code Playgroud)

我原以为这会导致错误,就像尝试声明名为 的变量时的情况一样class。据我所知,Java 人员非常小心,不破坏现有代码,因此我认为这可能是一个经过深思熟虑的选择。

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

kay*_*ya3 12

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

\n

自 Java 9 以来,由于在该版本中引入了几个新关键字,Java 语言规范对上下文关键字(最初的“限制关键字”和后来的“限制标识符”)和保留关键字进行了区分。JLS 9 ( \xc2\xa73.9 )中给出了基本原理:

\n
\n

另外十个字符序列是受限制的关键字:openmodulerequirestransitiveexportsopenstousesprovides、 和withModuleDeclaration这些字符序列仅在和产生式 (\xc2\xa77.7)中作为终结符出现时才被标记为关键字ModuleDirective。它们在其他地方都被标记为标识符,以便与 Java SE 9 之前编写的程序兼容。

\n
\n

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

\n


Axe*_*xel 7

好的,当再次查找constJLS 时,我看到 that recordis a contextual keywordsconstis just a keywords。上下文关键字根据上下文进行解析,当解析器确定它不是在查看记录声明时,它不会抱怨。

  • 关闭,但“record”(如“var”)也被限制为类型名称。所以允许有一个名为“record”的变量,但不允许有一个名为“record”的类。(所以你不能说“记录记录(记录记录){}”。)由于已建立良好的命名约定,这不应该是一个很大的负担。 (4认同)
  • 在不破坏现有应用程序的情况下添加关键字来发展 Java 的问题促使有人提议允许使用连字符连接的关键字。请参阅 [*JEP 草案:Java 语言的关键字管理*](https://openjdk.java.net/jeps/8223002)。 (3认同)