Java 语句,处理优先级 ( "dangling else" )



给定以下有效代码:

Boolean a = false;
if (a)
   System.out.println("A");
else
   System.out.println("!A");

根据文件,if包括其状态和内部statement也是statement。例如:

   if (b){
      System.out.println("B");
   }

statement

但是,当我们要用另一个语句替换现有语句时,它不应该触及整体逻辑,对吗?假设我们将(Expression)- statement替换为上面的if-statement:

Boolean a = false;
Boolean b = false:
if (a)
   if (b){
      System.out.println("A and B");
   }
else
   System.out.println("!A");

Java编译器将按如下方式解释代码示例(用大括号表示解释):

Boolean a = false;
Boolean b = false:
if (a){
   if (b){
      System.out.println("A and B");
   } else {
      System.out.println("!A");
   }
}

不是初始逻辑。

那么为什么用交换一个语句来替换另一个语句会改变逻辑呢?

从这个例子中可以清楚地看出,问题只是关于大括号,但是我找不到关于java处理这个问题的确切方式的信息,如果省略大括号。

关于这种行为有什么书面记录吗?为什么java更喜欢将else连接到最近的if,而不是在解析时遇到的第一个if ?

当然,答案在Java语言规范中。相关的章节是第14.5节,"语句",它准确地描述了这种情况:

与C和c++中一样,Java编程语言的if语句也存在所谓的"悬空else问题",下面这个格式错误的示例说明了这一点:

if (door.isOpen())
    if (resident.isVisible())
        resident.greet("Hello!");
else door.bell.ring();  // A "dangling else"

问题是外部if语句和内部if语句都可能拥有else子句。在这个例子中,我们可以推测程序员想让else子句属于外部的if语句。

最后:

Java程序设计语言,像C和c++以及在它们之前的许多程序设计语言一样,武断地规定一个else子句属于它可能属于的最里面的if

通过将其与最近的if相关联,您知道您只需要读取最近的if就可以理解逻辑。否则,您将阅读所有if和所有else条款来理解它们中的任何一个。

说你没有做最近的if,但至少做最近的if

if (a) 
  if (b) 
     something();
  else // if this is else to if (a)
     something();
else if (c) // what is this the else to?
  something();
else
  something();

当您有多个else子句时,如果else是针对最近的if

,则更容易阅读。

按预期工作,缩进没有任何意义。else指向最近的if,因此它属于if(b)你应该缩进代码:

Boolean a = false;
Boolean b = false:
if (a)
   if (b){
      System.out.println("A and B");
   } else
      System.out.println("!A");

但通常使用大括号总是好的做法{}

这是正确的行为。如果在If语句后面没有花括号,则只有第一个语句被视为真条件的一部分。您的示例的问题是,没有大括号来定义语句的范围,并且在求值b的条件后面有一个大括号。

在第一个if语句之后,第二个if语句使用花括号并建立语句的优先级。你应该像这样使用代码:-

Boolean a = false;
Boolean b = false:
    if (a){
       if (b)
          System.out.println("A and B");
    }
    else
       System.out.println("!A");

java程序的DOM,称为AST,抽象语法树,是一种更纯粹的结构,通常用作讨论代码的意义、语义的基础。

线性文本有许多解析缺点,例如:

-(-y) equal to y for most int values
--y

悬空的else是一个点。

在计算机科学中,有时只有声明性语言(函数,逻辑)在符号级别上处理。另一方面,C/c++是出了名的上下文化。

Java是一种面向对象的语言,这本质上意味着它在编译代码时遵循自下而上的方法。这就是为什么它将最新的if语句视为else部分的伴侣。

最新更新