【问题标题】:Is it legal to use `record` as a variable name even though it's a keyword?即使它是关键字,使用`record`作为变量名是否合法?
【发布时间】:2021-12-24 22:04:29
【问题描述】:

这让我感到意外:我能够声明一个名为 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。)

【问题讨论】:

    标签: java jls java-17 java-record


    【解决方案1】:

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

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

    另外十个字符序列是受限关键字:openmodulerequirestransitiveexportsopenstousesprovides 和 @ 987654332@。这些字符序列仅在它们作为终端出现在 ModuleDeclarationModuleDirective 产品中时才被标记为关键字(第 7.7 节)。它们在其他任何地方都被标记为标识符,以便与 Java SE 9 之前编写的程序兼容。

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 这真的很有道理。不难想象,“记录”一词在代码库中作为字段或局部变量名称出现的次数是巨大的。
      • 在不破坏现有应用程序的情况下添加关键字以发展 Java 的问题促使提出允许使用连字符关键字的提议。见JEP draft: Keyword Management for the Java Language
      • @BasilBourque 该文档引用连字符关键字只是几种可能的策略之一,包括“上下文关键字”、“保留标识符”等。实际上,我们可能会使用所有这些策略来平衡进化、表现力和兼容性。
      • 关闭,但record(如var)也被限制为类型名称。因此允许有一个名为record 的变量,但不允许有一个名为record 的类。 (所以你不能说record record(record record) {}。)这不应该是一个很大的强加,因为有完善的命名约定。
      猜你喜欢
      • 2016-10-24
      • 1970-01-01
      • 2021-09-11
      • 1970-01-01
      • 2016-05-04
      • 2012-12-02
      • 2019-12-01
      • 2011-09-02
      相关资源
      最近更新 更多