2012-10-17 56 views
5

这被看作是代码的Java语言中的片段:分支无法通过编译器

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

if(value <= 9) 
o = 8; 

System.out.println(o); 
} 

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

+3

错误是:变量o可能没有被初始化(System.out.println(o)) –

+2

为什么两个if语句而不是if..else? – CBredlow

+0

我只是在探索语言。这两个陈述没有特别的理由。 – uml

回答

5

编译器必须把value为可更改。声明它finalfixes 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); 
} 
+0

我很惊讶它不能轻易推测它在这种情况下是不可变的 –

+1

@BrianAgnew我只能猜测编译器不允许将两个'if'中的两个读取值视为访问相同的价值(并因此使两个条件互补)。 – dasblinkenlight

+1

编译器只能在检查明确赋值时对常量表达式进行操作。 'value> 9'和'value <= 9'都不是常量表达式,除非'value'是常量变量,它本质上是一个'final'变量。 – pingw33n

0

在编译:

编译器看到的,你没有初始化的变量的“o”,你是在系统输出打印。

你可以做到这一点:除非你说,否则

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

else 
o = 8; 

System.out.println(o); 
} 
0

初始化Ø前if语句声明后

o=0; 
0

按JLS (§16)每一个局部变量和非空字段必须明确赋值才可以用过的。编译器通过一些基本的静态分析来确保它。

明确赋值背后的思想是,对本地变量或空白最终字段的赋值必须发生在访问的每个可能的执行路径上。类似地,明确的未分配背后的想法是,在分配的任何可能的执行路径上,不允许其他分配给空白的最终变量。

静态分析器只能推导常量表达式的值($15.28)在您的示例中不是这种情况。

1

原始版本无法编译的原因是JLS section 16中的JLS'“明确分配”规则说o尚未明确分配。编译器用一个神秘的消息报告这个消息,说“o可能没有被初始化”。

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

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

  • 在声明中指定o
  • 将两个if语句替换为单个if/else语句。
  • 声明valuefinal

上次修复很有趣。它的工作原理是JLS明确的分配规则需要编译器将编译时常量布尔值表达式的值考虑在内。

本声明(与final加)

final int value = 9; 

意味着value是一个编译时间常数。这意味着value <= 9value > 9也是编译时常量。因此,JLS明确分配规则指出o之后

if(value <= 9) o = 8; 

明确指定的,可没有一个编译错误以后使用。


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

JLS在明确赋值规则中对表达式值的保守处理旨在避免一个Java编译器推断出明确赋值,但另一个不能赋值的问题。编译时常量表达式的子表达式可以通过简单地评估表达式来处理,并且JLS规则隐式识别这个表达式。