【问题标题】:Syntax with missed Expression for basic for-loop基本 for 循环的缺少表达式的语法
【发布时间】:2016-05-21 05:05:18
【问题描述】:

几天前,我和我的同事讨论了这段 Java 代码:

for( ; ; ) { }

这里没什么特别的,只是一个无限循环。

但我们想知道为什么这在语法上是正确的。如果您查看JLS §14.14.1,您会看到:

for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement

我知道ForInitForUpdate 可以省略。但至少我希望 Expression 是强制性的,就像在 while-loop 中一样:

while() {} // compile error, Expression is missed

那么为什么在 for 循环中可以省略 Expression?甚至有人想得更多——为什么错过的表达式解析为true?我的期望是空的表达式被解析为false

同样的想法也适用于其他语言(我已经用 C 和 JavaScript 尝试过,但我相信每一种带有 for 循环的语言都会以这种方式运行)。

为什么表达式子句在 for 循环中不是强制性的(但在 while 循环中)?为什么空表达式解析为true 而不是false

【问题讨论】:

  • 如果你担心这个,你手头的时间太多了 :)
  • 有趣的是,for(;;)while(true) ae 都只替换为一条 goto 0 指令:P
  • @tokamak 成就了我的一天:D
  • @WaleryStrauch - 是的。这里也一样。
  • @JasonZ:这两个问题是天壤之别。这是在询问词法结构,not 为什么一条语句使用特定的表达式编译而另一条则没有。

标签: java c for-loop


【解决方案1】:

基本原理从in JLS 14.14.1.1 开始,一直持续到 14.14.1.2,重点是我的。

如果ForInit 部分不存在,则不采取任何措施。

如果Expression 不存在,或者它存在并且其评估(包括任何可能的拆箱)产生的值为真,则执行包含的Statement...

JLS 允许空白的ForInitExpressionForUpdate 语句,并且有条件处理它们的缺席,因此省略它们是可以接受的。

不允许使用while 循环、per JLS 14.12 这样做。

Expression 的类型必须为 booleanBoolean,否则会发生编译时错误。

因此,规范不允许通过空白表达式,因为这会导致上述编译时错误。


如果您正在寻找更多历史原因,C specification mandates this as well

由于 Java 从 C 中汲取了大量灵感(并且大部分都在其中实现),因此 Java 循环的行为与 C 的循环相似是非常有意义的,这就是它们的行为方式:表达式在 C 的 for 语句中是可选的,并且在其while 声明中是强制性的。

【讨论】:

  • 是的...我也看到了 JLS。但我的问题是“为什么”会这样?
  • “因为 Oracle 这么说”是您可以从这里继续做的最好的事情。它也与 C 一致,Java 主要基于 C。
  • 我写这个问题是因为我希望有人能给出比“因为 Oracle 这么说”更好的答案。当然,我相信 java 使它与 C 保持一致。但是这个决定的最初原因是什么?也许有历史原因,例如“以这种方式实现编译器更容易”或“只是错误 - 但出于兼容性原因,之后没有更改”。也许还有其他原因......我的问题旨在找出这一点。
  • @WaleryStrauch:我添加了另一个资源,但最终的答案是仍然“因为 Oracle/Sun 是这么说的”。有强有力的证据表明它是从 C 中获得灵感的,这是有道理的,但这个决定仍然是由最初的语言框​​架制定者做出的。
猜你喜欢
  • 2019-10-07
  • 2019-12-07
  • 2019-03-13
  • 2012-05-13
  • 1970-01-01
  • 2021-12-22
  • 2021-10-23
  • 1970-01-01
  • 2018-05-21
相关资源
最近更新 更多