给定以下有效代码:
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部分的伴侣。