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

Try {} finally {} построить с возвращаемыми значениями

Мне было интересно, почему следующий код будет принят компилятором Java:

public class Main {

    public static void main(String ... args){
        System.out.println("a() = " + a());
    }

    public static String a (){
        try {
            return "a";
        }catch(Throwable t){
        }finally{
            return "b";
        }
    }
}

Это может и не должно работать. Спецификация java заявляет, что блок finally будет выполняться всегда, но в то же время возвращаемое значение уже указано. Поэтому либо вы не можете выполнить оператор return "b", потому что вы вышли в return "a", что было бы неверно.

Однако другой вариант заключается в том, что вы выполняете оператор return "b" и тем самым полностью игнорируете инструкцию return "a"...

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

В основном, мой вопрос: помимо плохой практики, будет ли это считаться ошибкой Java, или это имеет другие прекрасные применения, кроме обфускации?

Изменить:

Вопрос не столько в том, что это ошибка, но и в том, что у него есть хорошие варианты использования?

4b9b3361

Ответ 1

Все работает точно так, как ожидалось, никаких ошибок здесь. Когда у вас есть сомнения, JLS - ваш спаситель:

JLS - 14.20.2. Выполнение try-finally и try-catch-finally:

Если выполнение блока try завершается внезапно для любого другого причины R, тогда выполняется блок finally, а затем есть выбор:

  • Если блок finally завершается нормально, то инструкция try завершается внезапно по причине R.

  • Если блок finally окончательно завершится по причине S, попробуйте оператор завершается внезапно по причине S (а причина R - отбрасывают).

Он переопределяет значение в блоке try.

return внутри finally отбрасывает все исключения, которые могут быть выбраны в try.