为什么我会感到烦恼"变量未初始化"编译器错误,这个变量在任何情况下都会被初始化?
File[] files;
final boolean doItFirst = evaluateOnce();
if (doItFirst)
files = listFiles();
changeDirectory();
if (!doItFirst)
files = listFiles();
// next line is flagged error by the java 7 compiler, although files as in any case been initialized
if (files != null && files.length > 0 ) {
// ...
}
答案 0 :(得分:3)
技术原因是关于if
语句的明确赋值的JLS规则;见JLS 16.2.7。
这些规则(和其他规则)声明v未在
中明确分配 if (c) {
v = 1;
}
if (!c) {
v = 2;
}
但它明确地分配在:</ p>
if (c) {
v = 1;
} else {
v = 2;
}
底线是Java决定变量&#34;是否可以不被初始化&#34;基于一些简单规则的应用,而不是逻辑演绎。
(这种语言是以这种方式指定的,以避免编译器实现可能复杂且昂贵的逻辑推理。如果一个Java编译器比另一个编译器做得更好的推理,这也避免了假设的可移植性问题。)
对于它的价值,我会将您示例的相关部分编码为:
boolean doItFirst = evaluateOnce();
if (doItFirst) { // or get rid of the temporary variable
files = listFiles();
changeDirectory();
} else {
changeDirectory();
files = listFiles();
}
IMO,这比将files
预先初始化为虚拟值更好,因为它可以防止意外导致实际初始化被删除的代码更改。
答案 1 :(得分:1)
编译器可以告诉每个if
语句都尝试分配给files
,但它不会认识到这两个条件是互补的。如果需要,请将其视为编译器限制。
这是一个建议:
if (!doItFirst) {
changeDirectory();
}
files = listFiles();
if (doItFirst) {
changeDirectory();
}
这样方法调用的顺序是相同的,但是files
初始化超出了if
语句。
答案 2 :(得分:0)
编译器不知道if (doItFirst)
和if (!doItFirst)
是互补的(就编译器所知,doItFirst
的值在第一个条件之后和之前可能已经改变第二)。因此,无法确定您的变量是否会在所有情况下初始化。
如果您使用if-else条件,则可以避免此问题。
例如:
if (doItFirst) {
files = listFiles();
} else {
changeDirectory();
files = listFiles();
}
我不知道在哪里放changeDirectory()
,因为我不知道它如何影响listFiles()
来电。如果您想在两种情况下都致电changeDirectory()
,则可能需要在if
和else
条款中调用它(或在条件之前或之后将其置于其中)。
答案 3 :(得分:0)
你必须初始化你的数组:
library(data.table)
d <- data.table(a)
d[ , .(start = min(.I), len = max(.I) - min(.I) + 1, nonzero = (a != 0)[1]),
by = .(run = rleid(a != 0))]
# run start len nonzero
# 1: 1 1 2 FALSE
# 2: 2 3 2 TRUE
# 3: 3 5 1 FALSE
# 4: 4 6 3 TRUE
# 5: 5 9 3 FALSE
# 6: 6 12 1 TRUE
是的,逻辑上你认为不需要初始化你的数组,但这是不正确的,你只是在File[] files = null;
块中使用files = listFiles();
,没有别的,因为编译器问你初始化你的数组。
if