Java 分支可以';编译器看不见

Java 分支可以';编译器看不见,java,if-statement,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); } public void name(){ int值=9; INTO; 如果(值>9) o=5; 如果(值在编译过程中: 编译器发现您尚未初始化变量“o”,正在sysout中打印 你可以做到这一点: public void nam

这是Java语言的代码片段:

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

if(value <= 9)
o = 8;

System.out.println(o);
}
public void name(){
int值=9;
INTO;
如果(值>9)
o=5;

如果(值在编译过程中:

编译器发现您尚未初始化变量“o”,正在sysout中打印

你可以做到这一点:

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

else
o = 8;

System.out.println(o);
}

除非您另有说明,否则编译器必须将
视为可更改的。声明它为
最终值

public void name(){
最终整数值=9;
INTO;
如果(值>9)o=5;

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

o=0;
根据JLS,每个局部变量和非空白字段必须在使用前进行明确分配。编译器会进行一些基本的静态分析以确保它

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


静态分析器只能推断常量表达式的值,而在您的示例中并非如此。

原始版本未编译的原因是JLS中的“确定赋值”规则表示,
o
中未明确赋值。编译器报告此情况时会显示一条神秘的消息,说明“
o
可能尚未初始化”

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

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

  • 在声明中为
    o
    赋值
  • 将两条
    if
    语句替换为一条
    if
    /
    else
    语句
  • 声明为
    最终值
最后一个修正是有趣的,它工作的原因是JLS确定赋值规则要求编译器考虑编译时常量布尔值表达式的值

本声明(添加了
最终版本

这意味着
value
是编译时常量。这意味着
value 9
也是编译时常量。因此,JLS明确分配规则声明
o

    if(value <= 9) o = 8;

if(值错误为:变量o可能尚未初始化(System.out.println(o))为什么是两个if语句而不是if..else?我只是在探索语言。这两个if语句没有什么特别的原因。我很惊讶它不能轻易地推测它在这个语言中是不变的scenario@BrianAgnew我只能猜测编译器不允许将两个
if
s中的
value
的两次读取作为访问相同的值(从而使两个条件互补)。在检查确定赋值时,编译器只能对常量表达式进行操作。
value>9
value
    final int value = 9;
    if(value <= 9) o = 8;