Java中的新关键字

在不久的将来,新功能将以Java语言出现,目前正在Valhalla,Panama和Loom项目下进行开发。 扩展语言不是一件容易的事,尤其是不是强调向后兼容性的语言。 因此,为了使它们顺利地集成到Java中,语言架构师必须解决累积的基本问题。

昨天(1月8日),作为Oracle Java语言架构师在Oracle工作的Brian Goetz Project Amber邮件列表中一封信“船长,我们需要更多关键字!”。 他提出了一种方法来解决向语言添加新关键字的问题。 结果,关键字可能以非nullnon-finalfinal -finalthis-return等语言显示 (完整的列表在帖子末尾的空白处等待着您)。

由于过去在语言中很少出现此问题,因此他们通常对此不怎么考虑,而是“试图尽快摆脱困境”。 由于将来现有方法的缺点,因此它们的应用将成问题,因此,决定提前进行工作。 建议的解决方案:尝试扩​​展可用作关键字的词汇形式集:允许使用连字符分隔的关键字,这些连字符将使用一个(或多个)现有关键字或保留的标识符。

重要说明:Brown指出,仅提供新关键字作为说明性示例,您不应专注于它们。 但是,很明显,我们已经收到了关于该语言的语法将来可能如何变化的深思熟虑的演示-作者在信中提到,该思想将有助于向Java添加许多理想的缺少的语言构造。

“旧”方法


如您所知,如今在Java语言中有50个关键字( keyword ),被禁止用作变量的标识符。 JLS语言规范的第3.9节中提供了完整列表。 自从该语言的第一个版本以来,此列表变化不大-在版本4中仅添加assert ,在5中枚举 ,在9中添加_ 。除了它们之外,还存在“保留标识符” -truefalsenull-行为类似于关键字方式。

当开发人员需要在语言中添加新的关键字时,他们必须采用以下方法之一。

  • 强制所有权转移:我们将以前是标识符的词转换为关键字(例如assert )。
  • 处置:现有的关键字开始以从未使用过的方式使用(例如注释值或默认方法使用default)。
  • 不用它:找到一种不需要新关键字的语法使用方法-例如,对注释使用接口而不是注释 -或完全放弃该功能。
  • 创建可见性:使用英勇的语言成就( 受限关键字,保留类型名称 )来创建上下文相关关键字的错觉。

从原则上讲,通常可以使用这些方法中的任何一种,但是每种方法都有其缺点,并且对于严重的语言全面扩展而言,仅这些方法显然是不够的-对于将来的创新,有必要消除无法完全扩展语言语法的能力。

新增关键字


以下是反对“公正”采用和增加新词的论点。

  • 所选关键字越方便和受欢迎,它在程序源代码中出现的频率就越高,这将增加该语言的不兼容性(例如,当assert单词出现在Java SE 1.4中时,所有测试框架都停止工作)。
  • 开发人员消除这种代码不兼容的成本,从小的(重新命名局部变量)到致命的(当接口方法或公共类型无效时)的成本差别很大。
  • 语言开发人员最可能使用的词是流行的标识符(例如valuevarmethod );
  • 如果您选择源代码中很少使用的单词,并且与之发生的冲突更少,那么您将必须使用诸如通常_but_not_always_final之类的结构 ,自然希望避免使用该语言。
  • 但是,如果您选择了很少使用的单词,那么使用该方法的频率就太高了-破坏兼容性不是很好,并且没有那么多成功的组合。

重用“旧”关键字


关于“仅仅”继续使用这些词语,有一些考虑。

  • 在许多编程语言中都发现了在不同上下文中重用关键字的先例(Java的一个示例是使用( (ab)usefinal来表示“不可更改”,“不可重新定义”和“不可扩展”)。
  • 有时,这种方法很有意义并且本身就可以实现,但通常不是优先事项。
  • 随着时间的流逝,对一组关键字的要求集会不断扩大,这可能会变得很有趣-没有人愿意在其代码中使用null final
  • 如果您觉得后者有些夸张,请记住,在研究JEP 325时,他们认真建议使用新的switch结构来描述具有不同语义的开关 -如果您以同样的方式继续,十年后我们可以新新开关

如何在没有新关键字的情况下生活? 正如某些人所暗示的,完全停止参与语言的发展是可能的。 但这并不严重,也不适合其他人的意见,因为开发人员对语言的新功能有着浓厚的兴趣。

内容相关关键字


乍一看, 用来在代码中提供特定含义但不是保留字( 在C#中使用 )的上下文关键字似乎是相同的“魔杖”,但在这里Brian会根据实践提出自己的使用观点(例如,Java 10中的var实现,不是关键字,而是保留类型name )。 为了换取添加新关键字而不必“破坏”现有程序的错觉,我们增加了语言的复杂性和失真性。

规范编写者,编译器和IDE很难使用上下文关键字。 在涉及一种或两种特殊情况的情况下,这不会引起问题,但是当它们开始在任何地方使用时,将转化为更高的支持代码成本或错误的尾巴。

可以忽略这一点-他们说,这不是语言用户的问题,而是语言创建者以及编写编译器和IDE的人的问题。 但实际上,每个人都在受苦。 对于IDE来说,这可能是一个严重的问题:需要更多的输入来猜测开发人员要输入的内容-上下文关键字或标识符。 结果,用户在语法突出显示,自动完成和重构功能方面的工作变得越来越差。

您可以使用此工具,但请谨慎操作。

舌头变形


看来,这些方法所带来的问题-笨拙的语法,不必要的生活复杂性和错误-原则上,我们可以忍受。 但是还有另一个不是最明显的问题-使用关键字的细微差别导致语言本身的设计失真。

对于Java开发人员而言,如今写接口而不是注释是司空见惯的,但是每个人都同意使用友好的术语注释而不是@和“ old”关键字的组合会更合乎逻辑。

另一个示例:可用修饰符集(公共,私有,静态,最终等)不能称为complete-我们不能说不是finalstatic的任何内容。 反过来,这意味着您无法创建默认情况下变量或类为final或成员默认情况下为静态的功能,因为无法指示我们要放弃此修饰符。

对于使用该语言的人来说,这个问题并不那么明显-但是该语言本身的作者由于渴望进一步开发它,而不断遇到它,因此我们所有人都必须为做出这样的决定而付出代价(显式地,隐式地)。

以上所有结论本身就说明了这一点:我们需要另一个关键字来源。

拟议的解决方案


在该语言的实验功能中,使用一种语法来预先指定新的关键字,其中新的关键字本身前面带有两个下划线(例如,在原型Valhalla项目中__ByValue )。 做出此决定的原因是可以理解的-您需要指出这是一个临时替换,将来您需要为此做出最终语法的决定,与此同时,您可以轻松避免与现有代码的冲突。 有人建议对新关键字使用类似的格式-从一个或两个下划线开始-但这种解决方案不能称得上漂亮,因为在这种情况下,普通和新关键字会引起混淆。

因此,建议使用使用连字符构造的关键字,该关键字将使用一个或多个“旧”关键字或保留的标识符。

受限制的关键字不同,此方法将产生更少的解析问题,因为(以下为示例) not-null不能与减法表达式混淆,并且词法分析器始终可以确定ab是三个标记还是一个标记。 因此,我们为创建与现有源代码或彼此不大可能冲突的关键字提供了新的机会。 最重要的是,它们更有可能具有有意义的名称,因为该语言的创建者想要添加到Java中的大部分内容都基于现有的语言构造,例如non-null

作为新关键字的示例,给出了新关键字位置的可能候选者(我记得作者认为,此列表目前仅是说明性的):

- 非null ;
- 非决赛
-package-private (默认情况下,该类成员的访问级别的修饰符,当前未以任何方式指示);
- 公众阅读 (公开阅读,私人记录);
- 空检查
- 静态类型Valhalla必需的概念;表示与类的特定专业相关的静态信息,而不是与类本身有关的静态信息);
- 默认值
- 最终决赛 (现在应该使用“ 稳定”注释完成),
- 半决赛 (作为密封的替代);
- 穷举开关 ;
- 枚举类注释类记录类 (语言作者可以使用这些关键字来代替枚举接口) (如果有机会的话);
- 此类 (描述当前类的类文字);
- 此返回 (通常要求添加一种方法来将setter / method-builder标记为返回其接收者)。

当然,还有其他词法方案的变体,根据这些变体,有可能组合关键字,以使它们与源代码已经编写的关键字最小地重叠。 提议的连字符对于汽车和人类都足够可读。

可以理解的是,这种方法绝不排除与之前使用过的方法一起使用的可能性,而是将与它们一起使用。

Source: https://habr.com/ru/post/zh-CN435540/


All Articles