Java: как объявить final переменную, которая инициализируется внутри блока try - catch? - PullRequest
15 голосов
/ 19 февраля 2012

У меня есть переменная, которая не должна изменять свое значение после ее инициализации, поэтому я хочу определить ее как конечную переменную.

проблема в том, что переменная должна быть инициализирована в попыткеблок, поэтому я получаю следующие проблемы:

У меня есть следующий код:

Connection conn = null;
try {
    conn = getConn(prefix);
    [...do some stuff with conn...]
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
} finally {
    closeConnection(conn);
}

Если я объявляю переменную как final, не инициализируя ее как ноль, я получаю 'Localпеременная conn, возможно, не была инициализирована 'в блоке finally.С другой стороны, если я объявляю его окончательным и инициализирую его нулевым, я получаю ошибку «Конечная локальная переменная conn не может быть назначена» в блоке try.

EDIT: после ответа lxx я пришел сэта версия

try {
    final Connection conn = conn = getConn(prefix);
    try {
        return selectAll(conn, sql, params);
    } catch (Exception e) {
        throw new DbHelperException("error executing query", e);
    } finally {
        closeConnection(conn);  
    }
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
}

То есть, как это сделать?

-

Извлеченный урок:

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

-

EDIT: найдено два вопроса напереполнение стека о том, когда использовать final

Когда следует использовать final для параметров метода и локальных переменных?

Использование модификатора "final", когда это применимо в Java

Ответы [ 4 ]

7 голосов
/ 19 февраля 2012

Вы можете обрабатывать исключения более точно. Если вы получаете исключение, открывающее соединение, вам не нужно закрывать его в блоке finally, я полагаю. Если после этого вы получите исключение в блоке try и обработаете исключение в новом вложенном блоке try-catch, вам не нужно определять переменную снаружи. Что-то вроде:

    try {
        final Connection conn = getConn(prefix);
        try {
            //code using conn
        } catch (Exception e) {

        } finally {
            closeConnection(conn);
        }
    } catch (DbHelperException e) {
        throw new DbHelperException("error opening connection", e);
    }
2 голосов
/ 19 февраля 2012

Как насчет этого?

Connection temp = null;
try {
    temp = getConn(prefix);
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
} finally {
    closeConnection(conn);
}
final Connection conn = temp;
0 голосов
/ 19 февраля 2012

Почему ты хочешь, чтобы это было окончательно?Если вы хотите передать его анонимному внутреннему классу, вы можете сделать следующее:

Connection conn = null;
try {
    conn = getConn(prefix);
    final Connection finalConn = conn;
    // pass it to inner class here
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
} finally {
    closeConnection(conn);
}

Единственная проблема (и довольно большая) с этим решением состоит в том, что вы закрываете соединение, как только выходите из него.блок.Поэтому, если вы сразу не объявите и не вызовете свой внутренний класс, этот шаблон не сработает.

В любом случае, я бы, вероятно, перефразировал бы все это на вашем месте, сделав вместо этого prefix finalи делегирование обработки соединения внутреннему классу anon.

0 голосов
/ 19 февраля 2012

Можете ли вы попробовать назначить его в блоках catch и finally?Вот так:

Connection connTemp = null;
final Connection conn;
try {
    connTemp = getConn(prefix);
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
} finally {
    closeConnection(conn);
}
conn = connTemp;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...