2016-01-11 2 views
6

Почему результат следующего кода равен 3, почему, наконец, нужно завершить работу и выйти из метода, даже если компилятор проверяет сначала и почему возврат в попытке не завершает метод?попробуйте/наконец, не поймайте с заявлением о возврате?

public int returnVal(){ 
    try{ 
     return 2; 
    } 
    finally{ 
     return 3; 
    } 
} 
+1

Блок 'finally' всегда вызывается в конце, поэтому он называется« наконец »(подумайте« попробуйте это, поймайте любое исключение и, наконец, сделайте это »). – Thomas

+2

Блок 'finally' * всегда * выполнен независимо от того, что .. –

+0

Да, я понимаю это, но почему компилятор игнорирует оператор return в try, даже если он попадает в него во время выполнения, почему возвращение в try не делает завершение метода –

ответ

4

См JLS 14.17

Это можно увидеть, то, что оператор возврата всегда завершается преждевременно.

В предыдущих описаниях говорилось «попытки передать управление», а не просто «передает управление», потому что, если в методе или конструкторе есть какие-либо попытки (§14.20), в чьи блоки try или catch содержатся оператор return, наконец, предложения этих операторов try будут выполняться, чтобы быть наиболее внутренним до внешнего, до того, как управление будет передано вызову метода или конструктора. Резкое завершение предложения finally может привести к нарушению передачи управления, инициированного оператором return.

Эссенциально проверьте фразы attempts to transfer control и последнее предложение. Попробуйте возвратить попытку переноса элемента управления, после которого последним будет disrupt the transfer of control initiated by a return statement.

Другими словами, попытка attempts to transfer the controll, но так как выполнение блока finally все еще открыто для выполнения и содержит оператор return, попытка передачи управления в блоке finally имеет более высокий preceding. Вот почему вы видите значение 3, которое возвращается внутри блока finally.

4

finally выполнен до возврата значения от try (или catch).

Если в finallyreturn заявление присутствует перезаписывает возвращение try (или catch) блока.

Так и в этом случае возвращение наконец побеждает:

try { 
    // Exception thrown 
    return 2; 
} catch (Exception e) { 
    return 1; 
} finally { 
    return -1; // Always returns -1 also if a return statement is present in the try and in the catch clause 
} 
+0

+1, поскольку это было намного легче понять, чем верхний ответ (конечно, по цене меньшей информации). – domsson

0

Блок finally всегда выполняется до того, как управление возвращается вызывающей функции. Итак, в этом случае перед возвратом 2 он будет окончательно называться и будет возвращаться 3.

1

Почему возвращение в попытке не завершает метод?

Is it bad practice to return from within a try catch finally block?

Вы должны знать, что когда вы положили возврат внутри примерки поймать заявление, само возвращение удерживается и управляется блоком обработки Exeption.

Блок исключение запоминаются только ваше возвращение, и это действительно возвращает его только после того, как все проверки сделаны, что вовсе не означает, что, наконец, блок будет действительно иметь влияние на возвращение:

public int returnVal() { 
    int i = 0; 
    try { 
     return i; 
    } 
    finally { 
     i = 99; 
    } 
} 

В в этом случае возврат будет равен 0.

Но в случае, о котором вы упомянули в своем вопросе, вы оказываете влияние на возвращение во второй раз, и поскольку блок исключений не хочет, чтобы ваше возвращение прошло, пока оно не будет выполнено с ВСЕ его верификация, вы всегда сохраняете возвращаемое значение 2 раза в своем блоке исключений. Результат всегда будет 3.

Просто имейте в виду, что если вы положите ответ внутри try-catch-finally, то возврат не вернется, пока не завершится последний блок; само возвращение просто хранится до тех пор, пока все не будет проверено.