编译器无法看到的分支

时间:2012-10-17 14:24:26

标签: java if-statement

这是Java语言中的代码片段:

 public void name(){
int value = 9;
 int o;
if(value > 9)
 o = 5;

if(value <= 9)
o = 8;

System.out.println(o);
}

为什么编译器在考虑值的最后一个选项时看不到第二个if语句? 它不会编译。 最好的问候

5 个答案:

答案 0 :(得分:5)

除非另有说明,否则编译器必须将value视为可更改。声明final fixes the problem

public void name(){
    final int value = 9;
    int o;
    if(value > 9) o = 5;
    if(value <= 9) o = 8;
    System.out.println(o);
}

答案 1 :(得分:1)

原始版本无法编译的原因是JLS section 16中的JLS“明确赋值”规则表明o尚未明确分配。编译器使用一条神秘的消息报告此消息,该消息表明“o可能尚未初始化”。

现在,任何具有简单演绎技巧的人都可以看到第二个if条件是第一个if条件的否定,因此变量实际上总是被初始化。但是,JLS不允许编译器进行该推导。 JLS说这是一个错误......

有很多方法可以解决这个问题。例如

  • 在声明中为o分配内容。
  • 使用单个if / if语句替换两个else语句。
  • value声明为final

最后一个修复很有意思。它工作的原因是JLS明确赋值规则要求编译器将编译时常量布尔值表达式的值考虑在内。

此声明(添加了final

    final int value = 9;

表示value是编译时常量。这意味着value <= 9value > 9也是编译时常量。因此,JLS明确赋值规则规定o

之后明确赋值
    if(value <= 9) o = 8;

可以在以后使用而不会出现编译错误。


明确的赋值规则旨在防止使用未初始化的变量,并防止空白final变量多次初始化。

JLS在明确赋值规则中对表达式值的保守处理旨在避免一个Java编译器推断某些内容被明确赋值但另一个不能分配的问题。可以通过简单地计算表达式来处理编译时常量表达式的子句,并且JLS规则隐式地认识到这一点。

答案 2 :(得分:0)

编译期间:

编译器发现你没有初始化变量'o'而你正在sysout中打印。

你可以做到这一点:

public void name(){
int value = 9;
 int o;
if(value > 9)
 o = 5;

else
o = 8;

System.out.println(o);
}

答案 3 :(得分:0)

在声明之后初始化o之前的if语句

o=0;

答案 4 :(得分:0)

根据JLS (§16),每个局部变量和非空白字段必须明确分配才能使用。编译器会进行一些基本的静态分析来确保它。

  

明确赋值背后的想法是必须在访问的每个可能的执行路径上发生对局部变量或空白最终字段的赋值。同样,明确取消分配背后的想法是,在任何可能的赋值执行路径上,不允许对空白最终变量进行其他赋值。

静态分析器只能推导出常量表达式($15.28)的值,而在您的示例中并非如此。