【问题标题】:Inconsistency with else statements?与 else 语句不一致?
【发布时间】:2017-05-30 06:05:18
【问题描述】:

这是我previous问题的修订版。

当使用 else-if 作为快捷方式时,我不确定为什么从语法上讲,它执行与嵌套 if-else 语句相同的功能。假设您有以下内容:

int score = 80;
if(score < 80) {
  System.out.println("C Grade");
} else if(score < 90) {
  System.out.println("B Grade");
} else if(score < 100) {
  System.out.println("A Grade");
}

如果我添加一些缩进,我会得到类似于:

if(score < 80) {
  System.out.println("C Grade");
} else 
  if(score < 90) {
    System.out.println("B Grade");
  } else 
    if(score < 100) {
      System.out.println("A Grade");
    }

这与编写嵌套的 if-else 语句相同:

if(score < 80) {
    System.out.println("C Grade");
} else { 
    if(score < 90) {
        System.out.println("B Grade");
    } else { 
        if(score < 100) {
        System.out.println("A Grade");
        }
    }
}

但是,我看到了一个主要区别。在第三个代码 sn-p 中,“else”语句有括号,其余的 if-else 语句嵌套在这些括号内。在第一种情况下,没有封装括号。那么,如果嵌套 if-else 语句时似乎需要括号,为什么 else-if 的第一个想法有效呢?我认为缺少控制流语句(例如 if、else、while 等)的括号会导致编译器仅评估以下行,例如:

if(condition)
    System.out.println("A");
    System.out.println("B");
//only prints "A"

【问题讨论】:

  • else-if 在 Java 中的行为类似于 else 后跟 if - 的内涵。缺少括号不会评估以下行,而是评估以下语句。因为 if (or if else) 是一个声明,所以它非常一致。
  • 提问时的提示 - 在你的标题中做出断言(例如假设 else 陈述不一致)将导致投票失败,因为人们可能不同意你的断言而不是试图帮助你.而是专注于您真正要问的内容,例如“你能帮我理解else if 语句的语法吗?”这将鼓励援助,而不是投反对票。

标签: java if-statement


【解决方案1】:

如果没有括号,则使用下面的语句,而不仅仅是下面的

if 语句包含

if (<condition>) <statement> else <statement>

写成几行也没关系。一般来说,Java 中任何地方都可能出现换行符,只要允许空格而不改变其含义(唯一的例外是在字符串文字和一行 cmets 中)。

【讨论】:

  • 啊!那么 if 和 else 都是一个语句?因此,当“else”没有括号时,它会查看 if 和 else 的第一个“对”,并对其进行评估?
  • 是的。 else 始终与最近的 if 匹配。
  • 只是为了澄清,if-else 分组是一个语句?但在这里面,还有对应“if”和“else”的语句?
  • @rb612 不确定我明白你的意思。嵌套语句可以任意复杂(包含循环、ifs、...)。
【解决方案2】:

首先,请注意ifelse 始终适用于它们后面的单个语句。您可以使用{ } 将多个语句组合成一个复合语句,但条件随后适用于单个{ ... } 语句。

考虑以下两个等效语句:

if (foo) {
  bar();
}

if (foo)
  bar();

在第一个中,if 适用于 { } 块(其中包含 bar();),而在第二个中,它直接适用于 bar(); 语句。可能不会立即明显的是{ } 不是创建复合语句的唯一方法。事实上,if 是另一个复合表达式,因此它可以是另一个 ifelse 语句的直接子代。例如:

if (foo)
  if (bar) {
    baz();
  }

完全有效(如果难以阅读)并且等价于:

if (foo) {
  if (bar) {
    baz();
  }
}

同样的概念也适用于else - 如果前面的条件为假,它后面的任何语句都将被应用,即使该语句本身是复合语句!

if (foo) {
  bar();
}
else
  if (baz) {
    biff();
  }

else 适用于整个 if (baz) 块,由于它只是一个(复合)语句,因此不需要额外的 { } 块。

确切的语法在JLS §19中指定,if语句的不同形式的语法在JLS §14.9中详细说明。请注意,没有提到 else if,因为它不是语言的正式部分,只是语法的(有意的)结果。


综上所述,我们不按照您描述的方式格式化代码的真正原因仅仅是因为它更难阅读。将else if 视为单个关键字并相应地缩进代码要简单得多。其他一些语言(例如Python)使用像elif 这样的单个关键字来简化语法,但这并不是必需的。

【讨论】:

  • 谢谢!!这很有帮助。我试图完全理解 - 在我的问题中写的第二个陈述中,第 4 行到最后是否都是一个陈述?从if(score &lt; 90)到结束
  • 嗯,是和否:) ifelse 的主体是 if-else 语句本身就是语句,因此也可以是 if-else 语句。换句话说,您的每个示例 is 都是一条语句 - 但这些语句由子表达式组成,这些子表达式也是有效的语句。
  • 我在回答中添加了一些指向 JLS 的链接,以防万一。
  • 再次感谢!所以只是澄清一下,因为“else”将查看下一个语句,它会将下一个 if 和 else 语句一起视为一个语句?因为如果它们不是一个语句,那么“else”只会评估嵌套的“if”而不是“else”
  • 我不知道根据关键字“看起来”的位置来思考有多大帮助。而是尝试根据定义 Java 语法的语法来思考。 if 关键字必须后跟一个布尔表达式,然后是一个语句。然后可以选择在其后跟else 和另一个语句。由于这本身就是一个有效的语句,因此可以将条件语句嵌套在另一个语句中。相比之下,else 不可能(根据语法)出现在 if 的主体语句之后之外的任何地方。
【解决方案3】:

括号不是流量控制机制。它们主要是一种声明分组机制。

简单的if else 语句的语法是:

'if' '(' expression ')' statement 'else' statement

“语句”可以是赋值语句、方法调用、嵌套的if 等等。但“陈述”不是两个陈述,或三个,或...

这就是{ } 出现的地方,因为

'{' statement-list '}'

根据Java语法规则实际上是statement。通过使用大括号,您可以(可能)将许多语句组合成一个语句。

如果您将这些知识应用到您的示例中,您认为自己看到的“神秘”行为将变得简单明了。

作为记录,建议您始终将 { } 块与 if 语句和循环一起使用,因为它使您的代码更易于阅读。


我认为 if、else、while 等控制流语句中缺少括号会导致编译器仅评估以下行。

你得出了一个错误的结论。在 Java 语言中,它(几乎)与您放置换行符的代码的含义无关。唯一的限制是您不能在关键字、运算符、标识符和文字等标记中间放置换行符。 (并且换行符结束 // 评论。)

顺便说一句,尝试通过像阅读文本一样阅读编程语言并猜测语法来学习编程语言是一种不好的方法。你会产生各种不正确的想法。更好的方法是阅读一本好的教科书或该语言的官方教程材料。

【讨论】:

  • 谢谢斯蒂芬,我同意。我已经学习 Java 多年了,这个想法刚刚出现,因为我已经习惯了使用 else if,但只是开始质疑它为什么有效。因此,我的第二个代码 sn-p 中的所有内容,从 if(score &lt; 90) 到结尾都是一条语句吗?
  • 所以为了确保我完全理解,如果没有大括号的 Java 的“else”块只计算下一条语句,如果它后面跟着一个 if-else,那么“if”和“else”是被认为是一种说法?否则,Java 不会评估“else”作为嵌套的一部分,对吗?
  • 比这更简单。在else 之后应该有一个声明。它可以是一个简单的方法调用或赋值语句。它可能是另一个if 声明。它可能是一个块语句。它只是一个声明。
  • 感谢您的回复。但是如果你没有花括号,那么 Java 将只评估下一条语句,它不会简单地评估 if 部分,而不是“else”部分,因为这些是单独的语句?或者 if 和 else 是一个语句?这就是我感到困惑的地方。
  • 不。 else 不是语句。 else 后面的语句是if ... else ... 语句的一部分。一个语句可以包含其他语句
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 2015-05-16
相关资源
最近更新 更多