Является ли хорошей практикой иметь оператор возврата в блоке try, когда возвращается возвращаемое значение из блока finally
Мне было интересно, это хорошая практика для return
из try
block?
package debug;
/**
*
* @author Owner
*/
public class Main {
public static void main(String[] args) {
System.out.println(fun());
}
static boolean cleanup() {
// Fail to cleanup.
return false;
}
static boolean fun() {
boolean everything_is_fine = true;
try {
System.out.println("open file stream");
return everything_is_fine;
} finally {
everything_is_fine = cleanup();
}
}
}
Я подумал, что false
будет напечатано. Однако вот вывод:
open file stream
true
Как вы можете видеть, если у меня есть оператор return
в блоке try
, я пропущу статус отказа во время очистки finally
.
Должен ли я иметь код как:
static boolean fun() {
boolean everything_is_fine = true;
try {
System.out.println("open file stream");
} finally {
everything_is_fine = cleanup();
}
return everything_is_fine;
}
Пока возвращается возвращаемое значение из блока finally, я должен избегать возврата из try?
Ответы
Ответ 1
Ваш предлагаемый код (в конце вопроса) в порядке. Вы можете вернуться из блока finally
, но вы не должны - например, eclipse показывает предупреждение "окончательный блок не завершается нормально".
Фактически, try/finally
напрямую не связаны с return
. Кажется, это так, потому что это единственная конструкция в методе, но после этого вы можете иметь другой код (например, уведомления о событиях), а затем вернуться.
Что касается вашего вопроса - вы не можете изменить значение возвращаемой переменной в блоке finally
, если оно уже возвращено. Поэтому не возвращайтесь с try
.
Ответ 2
Оператор return
определяет, какое значение возвращается, которое в момент выполнения оператора return
было true
. finally
меняет значение переменной everything_is_fine
, но это не меняет того, что возвратил уже выполненный оператор return
.
Вы можете добавить еще один возврат в finally
, который переопределит return
внутри try
:
static boolean fun() {
boolean everything_is_fine = true;
try {
System.out.println("open file stream");
return everything_is_fine;
} finally {
everything_is_fine = cleanup();
return everything_is_fine;
}
}
Однако использование finally
для изменения потока управления не считается хорошей практикой. Конечно, это возможно. Лучший способ сделать это в вашем случае:
static boolean fun() {
boolean everything_is_fine = true;
try {
System.out.println("open file stream");
} finally {
everything_is_fine = cleanup();
}
return everything_is_fine;
}
Btw, имя переменной должно быть изменено на everythingIsFine
за преобладающее соглашения об именах Java; -)
Ответ 3
Отвечаем за то, почему возвращается "true":
Если переменная возвращается из try, хотя возвращаемое значение переменных изменяется в последнем блоке, будет возвращено ранее установленное значение (в этом случае значение, установленное в блоке try). (конечно, в конце нет возврата)
Отвечайте за то, что вы хотите достичь:
Если вы хотите изменить значение, которое должно быть возвращено в блоке finally, следуйте вашему второму подходу. то есть:
static boolean fun() {
boolean everything_is_fine = true;
try {
System.out.println("open file stream");
} finally {
everything_is_fine = cleanup();
}
return everything_is_fine;
}
Ответ 4
Пока он считается плохой практикой, вы можете вернуться на finally
. Это также перехватывает любые другие return
, которые могли быть у вас в блоках try
и catch
. Доказательство:
class Main
{
public static String test() {
try {
except();
return "return from try";
} catch (Exception e) {
return "return from catch";
} finally {
return "return from finally";
}
}
public static void except() throws Exception {
throw new Exception();
}
public static void main(String[] args) {
System.out.println(test());
}
}
Будет напечатан "окончательный возврат". Посмотрите на ideone.
Блок finally
всегда выполняется (запрещен вызов System.exit()
или вытаскивание вилки питания)
EDIT: Обратите внимание, что в первом примере кода ничего не возвращается в блоке finally
, но если у вас есть return false
, ваш метод всегда будет возвращать false.
Ответ 5
Назначение функции everything_is_fine в блоке finally не влияет на возвращаемое. Для меня это выглядит плохо. Какое намерение?
Ответ 6
Если вам нужно вернуть что-то, что имеет зависимости от кода, запускаемого в блоке finally, вам нужно поместить свое возвращение за пределы блока try; как сказал кто-то другой, хорошая практика состоит в том, чтобы иметь только одно выражение о возврате.
Сказав это, я никогда не сталкивался с тем случаем, когда мое возвращаемое значение зависело от вычисления в блоке finally, и обычно я возвращал бы результат внутри try.