Подтвердить что ты не робот

Является ли хорошей практикой иметь оператор возврата в блоке 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?

4b9b3361

Ответ 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.