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

Java: попробуйте, наконец, выполнить кастинг

Я запутался в выполнении try-finally, когда в блоке try существует return;. В моем понимании блок finally всегда будет выполнен, то есть перед возвратом к вызывающему методу. Рассматривая следующий простой код:

public class TryCatchTest {
    public static void main(String[] args){
        System.out.println(test());
    }
    static int test(){
        int x = 1;
        try{
            return x;
        }
        finally{
            x = x + 1;
        }
    }
}

Результат напечатан на самом деле 1. Означает ли это, что блок finally не выполняется? Может ли кто-нибудь помочь мне с этим?

4b9b3361

Ответ 1

Когда вы возвращаетесь из блока try, возвращаемое значение сохраняется в фрейме стека для этого метода. После этого выполняется блок finally.

Изменение значения в блоке finally не изменит значение уже в стеке. Однако, если вы снова вернетесь из блока finally, возвращаемое значение в стеке будет перезаписано, и будет возвращен новый x.

Если вы напечатаете значение x в блоке finally, вы узнаете, что оно выполнено, и будет напечатано значение x.

static int test(){
    int x = 1;
    try{
        return x;
    }
    finally{
        x = x + 1;
        System.out.println(x);  // Prints new value of x
    }
}

Примечание: В случае возвращаемого ссылочного значения значение ссылки сохраняется в стеке. В этом случае вы можете изменить значение объекта, используя эту ссылку.

StringBuilder builder = new StringBuilder("");
try {
    builder.append("Rohit ");
    return builder;

} finally {
    // Here you are changing the object pointed to by the reference
    builder.append("Jain");  // Return value will be `Rohit Jain`

    // However this will not nullify the return value. 
    // The value returned will still be `Rohit Jain`
    builder =  null;
}

Рекомендуемое чтение:

Ответ 2

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

Из спецификации языка Java, 14.17: Оператор return:

Оператор return с выражением пытается передать управление вызывающему метода, который содержит его; значение выражения становится значением вызов метода.

...

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

Ответ 3

Вы возвращаете x перед тем, как выйти из try. Я бы сделал это:

public class TryCatchTest {
    public static void main(String[] args) {
        System.out.println(test());
    }
    static int test() {
        int x = 1;
        try {
            do something with x.
        } finally {
            do something that will happen even in case of error;
            x = x + 1;
            return x;
        }
    }
}