Как сделать эту переменную ссылкой `final`, как мне заставить ее скомпилироваться чисто?

#java #final #idioms

#java #Финал #идиомы

Вопрос:

Я хочу создать result переменную final , как мне структурировать этот код, чтобы он компилировался чисто? Я знаю, что делал это в прошлом, но я не могу вспомнить, как я структурировал это, чтобы заставить это работать.

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

 private boolean someMethod()
{
    final boolean resu<
    try
    {
        // do the logic here that might throw the following
        // exceptions
    }
    catch (final IOException ioe)
    {
        result = false;
    }
    catch (final ClassNotFoundException cnfe)
    {
        result = false;
    }

    return resu<
}
  

Я не могу поместить result = true в try блок, потому что он не будет компилироваться с обоими блоками catch, жалующимися на то, что конечная переменная, возможно, уже назначена.

Я не могу поместить это в finally блок, потому что это вызвало бы те же жалобы, что и в try блоке?

Я хочу иметь возможность устанавливать result = один и только один раз.

Итак, что вы устанавливаете result = true; , чтобы заставить ее скомпилироваться чисто?

Комментарии:

1. Зачем создавать локальную переменную final ?

2. Я делаю все final настолько, насколько это возможно, потому что это значительно упрощает отладку, документирует намерение назначить переменную один и только один раз , а также является подсказкой по оптимизации для компилятора в большинстве случаев. Я не собираюсь спорить с этим аспектом, я знаю , что создание как можно большего количества ссылок на переменные final значительно повышает качество базы кода.

3. @Джаррод Роберсон: Для меня в данном случае эта «оптимизация» снижает качество кода (то есть читаемость). Нет причин объявлять result как final , особенно когда это сделает ваш метод излишне более сложным. В остальном, кроме этого случая, я полностью согласен с вами. 🙂

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

5. компилятор отловит ошибки, если другие места в моем коде, которые должны установить это, попытаются перезаписать это ? ЭТО ЛОКАЛЬНАЯ ПЕРЕМЕННАЯ!

Ответ №1:

Намного проще не задавать переменную.

 private boolean someMethod() {
    try {
        // do the logic here that might throw the following
        return true;

    } catch (IOException ioe) {
        // handle IOE
    } catch (ClassNotFoundException cnfe) {
        // handle CNFE
    }
    return false;
}
  

Комментарии:

1. Это то, о чем я тоже думал. Зачем устанавливать конечную переменную, которую вы просто собираетесь вернуть? исходный пример мне не понравился с точки зрения дизайна.

2. это решение цели, которой я пытался достичь , return в нескольких catch предложениях нехорошо, и неизменяемый result тоже нехорош. Читая этот ответ, я теперь вспоминаю, что именно такого подхода я придерживался в прошлом, спасибо, что освежили мою память.

Ответ №2:

Пытаться использовать final для принудительного применения «назначить ровно один раз» всегда сложно. Вы можете использовать вторую переменную:

 private boolean someMethod()
{
    boolean res;
    try
    {
        // do the logic here that might throw the following
        // exceptions
    }
    catch (final IOException ioe)
    {
        res = false;
    }
    catch (final ClassNotFoundException cnfe)
    {
        res = false;
    }
    final boolean result = res;
    return resu<
}
  

Но реальный вопрос в том, почему бы просто не удалить final квалификатор?

Комментарии:

1. Либо это, либо удалите try-catch блок и сделайте someMethod throw IOException и ClassNotFoundException .

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

3. этот ответ не достигает моей цели. Я не хочу загрязнять остальной мой код исключениями, которые не связаны с его работой

4. @Jarrod — Я не думаю, что анализ потока, выполняемый компилятором, позволит вам выполнять такого рода присваивание в блоках catch. Можно было бы возразить, что это должно быть возможно, но это просто не так. Я бы предложил не спорить с мэрией по этому поводу и просто заменить final объявление простым комментарием над объявлением.

Ответ №3:

Вы не можете переназначить значение final переменной, поэтому это невозможно.

редактировать: Также противоречит желанию объявлять переменную, которая является локальной для метода, как final и также изменять значение в том же методе — зачем вообще нужно объявлять ее как final в этом методе?

Комментарии:

1. Я ни на что ее не устанавливал, я не пытаюсь ее переназначать, я пытаюсь назначить ее только один раз , либо на true , либо false на.

2. Но final означает, что вы можете назначить только один раз в том же операторе, что и объявление — таким образом, оно не может быть объявлено, а затем назначено в блоке, подобном этому. Почему бы просто не удалить final модификатор из объявления, учитывая, что это только локальная переменная?

Ответ №4:

Если вы объявляете локальную переменную как final внутри метода, то значение этой переменной не может быть изменено внутри метода.

Удалите final из объявления result или вообще избавьтесь от result локальной переменной и возвращайте непосредственно из catch блоков и конца метода.

Комментарии:

1. возврат изнутри кучи catch блоков — ужасная практика.

2. возврат из нескольких мест в методе — плохая практика с самого начала, это обратная сторона GOTO , таким образом, возврат из нескольких блоков catch — плохая практика.

3. Интересное чтение, спасибо. Однако это был не самый важный момент моего ответа, который заключался в том, чтобы полностью избавиться от final или удалить result local, как Питер предложил в своем принятом ответе.