当我这样做时,
if(a>=b && a>=c) {
max = a;
} else if (b>=a && b>=c) {
max = b;
} else if (c>=a && c>=b) {
max = c;
}
System.out.println(max);
它给出一个错误(java: variable max可能没有被初始化),但是当我这样做时,
if(a>=b && a>=c) {
max = a;
} else if (b>=a && b>=c) {
max = b;
} else {
max = c;
}
System.out.println(max);
它的工作原理。为什么会这样?
在第一种情况下,所有编译器看到的是您有3个条件语句为max
设置值。因此,它认为存在一个可能的路径,其中所有条件都不为真,在这种情况下max
不会被赋值。
你和我可以看看这些条件,并明白其中一个必须是正确的。编译器不会考虑这些,它只是假设每个条件都可能为假。
当存在一个没有条件的else
时,编译器可以保证至少有一个赋值将被执行。因此没有错误。
在else if中,必须有一个条件。只有当条件满足时,它才会进入。在第一种情况下,如果所有条件都为假,那么max将保持未初始化,而在第二种情况下,如果if和else都为假,则else部分肯定会执行。因此,max在所有情况下都有一定的价值。
我假设你的变量声明看起来像这样:
int a = 0;
int b = 0;
int c = 0;
int max;
在System.out.println(max)中调用max时发生变量未初始化错误最重要的区别在这一部分:# 1
} else {
max = c;
}
# 2
} else if (c>=a && c>=b) {
max = c;
}
那么,for case#1编译器100%确定,即使您没有陷入任何前面的if-conditions ((a>=b &&)a>=c) (b>=a &B>=c)),您将在else块中结束,该块将处理其余情况。For case#2,但是,if树的最后一部分仍然是一个条件。编译器假定存在这样一种可能性,即(a>=b &&a>=c), (b>=a &&>=c)也不(c>=a &&C>=b)为真,因此,认为Max未初始化。
简而言之:else
语句的存在保证了max
是设置的。
编译器应用流分析检查局部变量是否被明确赋值,并且编译器足够聪明1检测在所有可能的代码路径中max
在使用之前是否被设置。
在Java语言规范第16章中有详细的定义。
1正如Feuermurmel在注释中已经说过的,编译器不分析条件表达式。从逻辑上讲,条件之一必须为真,我们人类肯定知道。但是这种对编译器的分析不会达到那个程度,可能是为了减少复杂性。
在您的第一个示例中,Java不确定if/else块是否被执行。所以,如果你输出max
,它可能仍然是空的。在第二个示例中,无论变量max
是什么,它都会有一个值(c
),如果不是在它上面的if/else链中确定的其他东西。这也取决于您如何初始化max
。例如,如果像这样声明max
int max;
if(a>=b && a>=c) {
max = a;
} else if (b>=a && b>=c) {
max = b;
} else if (c>=a && c>=b) {
max = c;
}
System.out.println(max);
max
从来没有被赋值,所以它是null。如果你实例化它
int max = 0;
if(a>=b && a>=c) {
max = a;
} else if (b>=a && b>=c) {
max = b;
} else if (c>=a && c>=b) {
max = c;
}
System.out.println(max);
即使max在if/else链中没有改变,它仍然有一个值要输出。
这个问题的答案很简单。当if语句不为真时,总是会运行else语句。您的IDE抱怨max可能没有初始化,因为它实际上不理解代码。为了避免它,你可以这样做:
int max = 0;
if(a>=b && a>=c) {
max = a;
} else if (b>=a && b>=c) {
max = b;
} else if (c>=a && c>=b) {
max = c;
}
System.out.println(max);