java"变量未初始化"延迟补充替代品

时间:2017-05-16 09:44:55

标签: java

为什么我会感到烦恼"变量未初始化"编译器错误,这个变量在任何情况下都会被初始化?

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 ) {
    // ...
}

4 个答案:

答案 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(),则可能需要在ifelse条款中调用它(或在条件之前或之后将其置于其中)。

答案 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