Ленивая проверка исправности инициализации: переменная может быть не инициализирована - PullRequest
2 голосов
/ 08 мая 2019

Я объединяю существующие функции импорта и экспорта, чтобы уменьшить количество раз, когда пользователю сообщают, что в соединении было отказано, в случае, если соединение получило отказ. Библиотека, которую я вызываю, имеет отдельные функции импорта и экспорта, а также комбинированную функцию импорта / экспорта. Функция экспорта требует, чтобы список файлов был экспортирован, в то время как объединенная функция сама определяет список (и внутренне вызывает функцию экспорта с этим списком). Поскольку пользователь может отключить импорт или экспорт, я хочу получить список файлов только при необходимости.

Я придумал этот код:

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 ]

1 голос
/ 08 мая 2019

Ваша логика звучит так, что files всегда будет инициализироваться для каждого случая, в котором есть ссылка на files.Однако, как вы и подозревали, компилятор не идет так далеко.Его статический анализ не учитывает значения переменных, чтобы определить, будет ли определенное условие всегда истинным или ложным.

В этом случае компилятор не учитывает, что files инициализируется, еслиmExport - это 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();
}
0 голосов
/ 08 мая 2019

Статический анализатор не является предельным ИИ.Иногда это может дать ложные срабатывания.Вы должны иметь возможность приглушить жалобы на эту конкретную строку, однако я бы посоветовал переделать логику всего блока кода, чтобы упростить его.

Также files = null является избыточным, так как files означает null если не инициализировано иначе.Это просто обманчивый анализатор.

...