Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Как работает return


Автор: AndrewMormysh 9.9.2008, 08:54
Объясните, пожалуйста, особенности поведения return в следующем примере:
Код

public class TryFinalyReturnDemo {
    public static int f() {
        try {
            throw new Exception();
        }
        catch (Exception e) {
            return 2;
        }
        finally {
            return 1;
        }
    }

    public static void main(String[] args) {
       System.out.println(f());
    }
}


Да, finally должен сработать всегда, но и return должен остановить выполнение метода и вернуть результат. Мне интересно что происходит в виртуальной машине и как устроен механизм перехода указателя стека при работе метода, в котором есть и return и finaly.

Автор: Platon 9.9.2008, 09:04
Классный вопрос, никогда не задумывался. Но по поведению программы легко определить механизм. После того как выбрасывается любой Exception, вызывается блок finally, затем блок с соответствующим Exception.

Автор: Дрон 9.9.2008, 10:07
Это известная штука, читал о ней некоторое время назад.

В C# запрещено писать return (и другие операторы перехода, например goto) в блок finally -- комилятор сразу ругается на ошибку.

Цитата(Platon @  9.9.2008,  09:04 Найти цитируемый пост)
После того как выбрасывается любой Exception, вызывается блок finally, затем блок с соответствующим Exception. 

Да вроде наоборот, сначала обрабатывается catch, потом уже finally.
Могу предположить, что в JVM есть некий регистр, который используется для возврата значения. Сначала в блоке catch вызов return 2 пишет туда 2, потом в finally вызов return 1 перезаписывает его и там остаётся 1. Но это только предположение.

И, кстати, этот пример можно ещё подсократить и получить совсем прикольный побочный эффект:
Код
try
{
     throw new Exception();
}
finally
{
      return;
}

Тут хоть и отсутствует catch, но исключение будет "проглочено" в finally и из метода мы выйдем совершенно без ошибок.

Автор: AndrewMormysh 9.9.2008, 10:15
Цитата(Platon @ 9.9.2008,  08:04)
После того как выбрасывается любой Exception, вызывается блок finally, затем блок с соответствующим Exception.

Немного поясню как я себе представляю суть процессов. Это плохо, что я не знаю как на самом деле происходит, но пока не знаю и где это посмотреть smile Надеюсь форум мне поможет. 

Итак, далее следует исключильное ИМХО: при вызове throw new Exception на стеке создается новый указатель на объект Exception и если нет обработчиков, то именно он и вернется из метода. Дальше, если есть обработчик, то заходим туда. Вот тут то и самое интересное, при вызове return в стек, в нашем случае, помещается возвращаемое значение 2 и... метод должен прервать свое выполнение, но потом механизм обработки искл. ситуаций всё равно заходит в блок finaly и выполняет в нем код (на сколько вообще он там корректно сможет отработать при разных вариациях - вопрос отдельный) и соответственно при вызове return в стек помещается очередное значение 1 (или выталкивает предыдущее и заносит новое - тут вопрос). На выходе из метода получаем 1.

В общем, это то, как я вижу это. Надеюсь, более квалифицированные специалисты прокомментируют с подробностями мои предположения.

Автор: SaSho 9.9.2008, 11:25
Можно и без Exception'ов. Вот этот код вернёт значение 1:
Код

    try {
      return 2;
    }
    finally {
      return 1;
    }


Автор: AndrewMormysh 9.9.2008, 12:00
Если обратиться к документации, например http://www.computer.edu.ru/lib/langref/ch06_10.htm, почти всё становится ясным. Думаю, нюансы по поведению return стоит искать в недрах java - как всё таки передается управление между строками кода.

Автор: w1nd 9.9.2008, 12:01
Как вообще работает return в ЯВУ очень хорошо показывает паскаль smile Заурядная там конструкция:

Код
Result := ...;
Exit;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)