Java 为什么编译器抱怨一个变量可能没有在一个永远不会访问它的分支中初始化?
考虑只有以下方法的类的主体:Java 为什么编译器抱怨一个变量可能没有在一个永远不会访问它的分支中初始化?,java,compiler-errors,Java,Compiler Errors,考虑只有以下方法的类的主体: Integer getA() { return 0; } Integer getB() { return 1; } void testJava1() { final Integer a1, b1; if ((a1 = getA()) != null && (b1 = getB()) != null) { System.out.println(a1 + " and " + b1); // fi
Integer getA()
{
return 0;
}
Integer getB()
{
return 1;
}
void testJava1()
{
final Integer a1, b1;
if ((a1 = getA()) != null && (b1 = getB()) != null)
{
System.out.println(a1 + " and " + b1); // fine
}
}
void testJava2()
{
final Integer a1, b1;
final boolean condition = ((a1 = getA()) != null) && ((b1 = getB()) != null);
if (condition)
{
System.out.println(a1 + " and " + b1); // variable might have been not initialized???
}
}
void testJava3()
{
final Integer a1, b1;
final boolean conditionA = (a1 = getA()) != null;
final boolean conditionB = (b1 = getB()) != null;
if (conditionA && conditionB)
{
System.out.println(a1 + " and " + b1); // fine
}
}
void testJava4()
{
final Integer a1, b1;
final boolean conditionA = (a1 = getA()) != null;
final boolean conditionB = (b1 = getB()) != null;
final boolean conditionC = conditionA && conditionB;
if (conditionC)
{
System.out.println(a1 + " and " + b1); // fine
}
}
为什么testJava2
无法编译?编译器报告
variable might not have been initialized
如果
b1
为null
,则条件将为false,因此b1
将永远不会在if
块中访问。为什么编译器没有足够的智能来检测呢?如果第一个条件失败,第二个条件将永远不会执行。这就是为什么b1可能不存在的原因initialized@SotiriosDelimanolis我认为问题不仅与短路有关,还与编译器不想太聪明,不想把为一条指令执行的嵌套计算与一条无关的指令联系起来有关。@Sotirios Delimanolis问题并非如此远的但它涉及:final boolean条件=((a1=getA())!=null)&((b1=getB())!=null)方法中的代码><代码>((a1=getA())!=null)和((b1=getB())!=null)代码>不是一个常量表达式。因此b1
在任何情况下都被视为未被编译器初始化,即使我们知道如果条件为true
,则意味着a1
和b1
都已初始化。我问题的主要目的是指出,相同的表达式移到了“if”之前的最后一个变量编译器认为b1未初始化。但将这个表达式分成两个逻辑上精确的表达式会使编译器认为b1再次正确初始化。我不知道确切的JLS语句,但奇怪的是,testJava3和testJava4都很好。@SotiriosDelimanolis我可以理解这与短路有关,但我从另一个角度看:如果这个表达式的第一部分(在testJava2中)由于错误结果而短路,那么就不需要触摸b1,并且整个条件为false,因此条件代码块将不会执行,也不需要以任何方式接触b1。这在testJava1中很明显-为什么表达式规则在“if”中发生变化?