延迟初始化完整性检查:变量可能尚未初始化

时间:2019-05-08 18:14:47

标签: java android lazy-evaluation lazy-initialization short-circuiting

我正在合并现有的导入和导出功能,以减少在连接确实被拒绝的情况下,用户被告知连接被拒绝的次数。我正在调用的库具有单独的导入和导出功能,以及合并的导入/导出功能。导出功能需要导出文件列表,而合并后的功能会自行找出列表(并在内部使用此列表调用导出功能)。由于用户可以关闭导入或导出,因此我只希望在必要时获取文件列表。

我想出了以下代码:

List<File> files;
if (mExport)
    files = ListFiles();

if (mExport && mImport && files.size() > 0) // Error is on files
    DoExportAndImport();
else if (mImport)
    DoImport();
else if (mExport && files.size() > 0) // No error here
    DoExport(files);

第二条if语句被标记为错误Variable 'files' might not have been initialized(但不是最后一条)。

在这里提供我的推理帮助:如果mExport为真,则files被初始化;但是如果mExport为假,则第二条if会短路并且永远不会到达files,因此files尚未初始化没有关系,因为它没有被使用。

我在这里忽略了什么吗?还是编译器无法解决这种情况?如果是后者,有什么办法告诉编译器将其关闭,我已经处理了吗?

为记录起见,在声明中初始化files = new ArrayList<>()确实会使编译器静音,就像files = null一样,尽管显然会导致其他错误;但是初始化一个我知道永远不会以任何方式使用或引用的值就像浪费时间一样。

2 个答案:

答案 0 :(得分:1)

您的逻辑是合理的,因为在每次引用files的情况下,files总是会初始化。但是,正如您所怀疑的,编译器并没有走那么远。它的静态分析没有考虑变量的值来确定某个条件是真还是假。

在这种情况下,如果filesmExport,则编译器不考虑初始化true。它只看到未从顶部files语句初始化if的可能性,并且该引用在该语句下面。

您可以通过重新安排逻辑,以便仅在if语句块中对其进行引用来提供帮助。

List<File> files;
if (mExport) {
    files = ListFiles();
    if (mImport && files.size() > 0) {
        DoExportAndImport();
    } else if (files.size() > 0) {
        DoExport(files);
    }
} else if (mImport) {
    DoImport();
}

答案 1 :(得分:0)

静态分析器不是最终的AI。有时可能会产生误报。您应该能够在这一特定行上消除抱怨,但是我建议您对整个代码块的逻辑进行重做以使其更简单。

除非另外初始化,否则files = null也是多余的,因为filesnull。这只是在愚弄分析器。