Java: как объявить окончательную переменную, которая инициализируется внутри блока try-catch?
У меня есть переменная, которая не должна изменять ее значение после ее инициализации, поэтому я хочу определить ее как конечную переменную.
проблема в том, что переменная должна быть инициализирована внутри блока try, поэтому я получаю следующие проблемы:
У меня есть следующий код:
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, не инициализируя ее значением null, я получаю "Локальная переменная conn, возможно, не была инициализирована" на блоке finally. С другой стороны, если я объявляю его окончательным и инициализирую его значением null, я получаю сообщение об ошибке "Конечная локальная переменная 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, но в этом случае я предполагаю, что минусы объявления переменных конечных перегрузок выгодны...
-
EDIT: найдено два вопроса о переполнении стека о том, когда использовать final
Когда следует использовать final для параметров метода и локальных переменных?
Использование "final" модификатор, когда это применимо в java.
Ответы
Ответ 1
Вы можете справиться с Исключениями более точно. Если вы получите сообщение об исключении, вам не нужно закрывать его в блоке 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
Как насчет этого?
Connection temp = null;
try {
temp = getConn(prefix);
} catch (Exception e) {
throw new DbHelperException("error opening connection", e);
} finally {
closeConnection(conn);
}
final Connection conn = temp;
Ответ 3
Почему вы хотите, чтобы он был окончательным? Если вы хотите передать его анонимному внутреннему классу, вы можете сделать:
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);
}
Единственная проблема (и довольно большая) с этим решением заключается в том, что вы закрываете свое соединение, как только покидаете этот блок. Поэтому, если вы не сразу объявите и не назовете ваш внутренний класс anon, этот шаблон не будет работать.
В любом случае, я бы, вероятно, перефразировал все это, если бы я был вами, сделав вместо этого prefix
final и делегируя обработку соединения внутреннему классу anon.
Ответ 4
Можете ли вы попытаться присвоить его как в блоках 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;