Рассмотрим, что на самом деле делает компилятор для оператора return, например, в tryOne (): он копирует ссылку на builder
обратно в среду вызывающей функции.После того, как это сделано, но прежде, чем управление вернется к вызывающей функции, выполняется блок finally.Таким образом, у вас есть что-то более похожее на практике:
protected StringBuilder tryOne() {
StringBuilder builder = new StringBuilder();
try {
builder.append("Cool");
builder.append("Return");
StringBuilder temp = builder;
return temp;
} finally {
builder = null;
}
}
Или, с точки зрения порядка, в котором операторы фактически выполняются (конечно, игнорируя возможные исключения), это выглядит примерно так:
protected StringBuilder tryOne() {
StringBuilder builder = new StringBuilder();
builder.append("Cool");
builder.append("Return");
StringBuilder temp = builder;
builder = null;
return temp;
}
Итак, установка builder = null
работает, но ничего полезного не дает.Однако запуск builder.append("something")
будет иметь видимый эффект, поскольку и temp, и builder ссылаются на один и тот же (изменяемый) объект.
Аналогично, то, что действительно происходит в trySeven (), является чем-то большим.как это:
protected int trySeven() {
int count = 0;
count = 99;
int temp = count;
count++;
return temp;
}
В этом случае, поскольку мы имеем дело с int, копии независимы, поэтому увеличение одного не влияет на другое.
Все, что сказано,факт остается фактом: размещение выражений return в блоке try-finally довольно явно сбивает с толку, поэтому, если у вас есть какой-либо выбор в этом вопросе, вам будет лучше переписать все так, чтобы все ваши операторы return выходили за пределы любой попытки-конечные блоки.