以下代码块给出了编译时错误。
while(false)
{
System.out.println("HI");
}
错误表示存在无法访问的语句。 但以下代码编译
boolean b=false;
while(b)
{
System.out.println("Hi");
}
我能想到的就是这个 - >在case-1中,false是一个文字,所以编译器发现它是无法访问的,并且在运行时检查条件块中的2变量b in,所以没有编译错误?
答案 0 :(得分:3)
编译器编写者无法决定将哪些条件标记为错误 - 规则在Java语言规范中,针对14.21 Unreachable Statements中的此问题。
相关的句子是:“如果while语句可以访问且条件表达式不是值为false的常量表达式,则可以访问包含的语句。”
在每种情况下,您都可以使用while语句。在第一个版本中,false
是一个常量表达式,其值为false,因此包含的语句不被视为可访问。在第二个版本中,b
根本不是常量表达式,因此包含的语句被视为可达。
将final
添加到b
的声明中会将while条件更改为值为false的常量表达式,从而使包含的语句无法再次访问。
在JLS中指定什么是编译时错误和不编译时错误的规则有一个好处,即所有Java编译器都应该接受同一组程序。规则通常不要求编译器进行数据流分析,可能是为了限制编写编译器的成本和难度。
答案 1 :(得分:2)
编译器看到while(false)
,它永远不会成立,因此您无法访问println
。这会引发错误。
同时,尽管while(b)
也永远不会成立,但编译器不会自动知道这一点,因为b
不会自动为假,它恰好是boolean
值false
,它可能会在某个时刻发生变化。 (它不在这里,但可能有)。
为了使这一点更加通用,编译器将查看变量的类型,而不是变量实际的变量。许多开始编程类的部分都涉及多态性和类型转换如何在某些情况下导致运行时错误,以及其他编译器错误。如果您碰巧选择了这样的课程,您可以在此将您的问题视为具有类似的解释。
答案 2 :(得分:2)
这对我有意义。虽然(false)永远不会成功评估,而在while(b)的情况下 - b的值可以在程序生命周期的某个时刻更新为true。
答案 3 :(得分:1)
编译器对事物并不是非常聪明。它会找到一个块,你可以证明它有一个可证明的错误状态,它会哭。给它这样的东西,javac
并不是连接到那个远。对人类来说显而易见的事情并不一定对计算机来说很明显,反之亦然。
答案 4 :(得分:1)
编译器看到while(false)
并且可以确定内部的块不会执行。
而在布尔值的情况下,b
的值在运行时被评估,所以它不会阻止你