попробуй / наконец заблокируй вопрос - PullRequest
7 голосов
/ 29 марта 2011

Нашел этот вопрос здесь

И я не могу понять, почему в первом случае печатается CoolReturn+1, а во втором случае CoolReturn? Как это работает?

Спасибо

====================

Что будет напечатано?

public void testFinally(){
    System.out.println(setOne().toString());

}

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        return builder.append("Return");
    }finally{
        builder.append("+1");
    }
}

Ответ: CoolReturn + 1

Немного сложнее:

public void testFinally(){
    System.out.println(setOne().toString());

}

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        return builder.append("Return");
    }finally{
        builder=null;  /* ;) */
    }
}

Ответ: CoolReturn

Ответы [ 7 ]

7 голосов
/ 29 марта 2011

Рассмотрим

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        return builder.append("Return");
    }finally{
        builder.append("+1");
    }
}

как

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        StringBuilder ret = builder.append("Return"); // 1
        return ret; // 2
    }finally{
        builder.append("+1"); //3
    }
}

, строка 1 выполнена, builder возвращается как результат.Затем выполняется строка 3, и к builder добавляется +1, затем возвращается ret, который является «ссылкой» на объект, на который ссылается builder.То же самое для второго случая.Надеюсь, это понятно.

6 голосов
/ 29 марта 2011

Первый:

Наконец, всегда срабатывает (при условии, что машина не разбилась или что-то еще). Таким образом, после возврата срабатывает блок finally, и, поскольку он имеет ссылку на объект «строитель», он добавляет к нему дополнительный токен.

Второй:

Блок finally срабатывает точно так же, как и раньше, но устанавливает нулевую ссылку на строитель. Объект все еще существует, потому что он все еще имеет ссылку на него.

2 голосов
/ 29 марта 2011

Когда он возвращает builder.append («Return»), копия ссылки на переменную builder помещается в стек.Тогда строитель устанавливается в нуль.Затем вызывающая сторона выталкивает копию ссылки из стека.

1 голос
/ 29 марта 2011

В первом примере в блоке finally вы управляете строителем строк с помощью добавления.

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

РЕДАКТИРОВАТЬ: Похоже, я получил удар.

0 голосов
/ 29 марта 2011

Это работает, потому что выражение return вычисляется до выполнения блока finally. Это становится очевидным, когда вы вызываете метод из оператора return вашего кода и добавляете операторы журналирования в ваши блоки try и finally. Соответствующее объяснение можно найти в JLS 3-е издание, 14.20.2 . Это одна из причин, по которой операторы return в блоке finally выдают предупреждение в IDE, например, Eclipse.

Образец шпунтового кода:

def doSomething() {
    def f = "something";
    try {
        return f += doSomethingMore()
    } finally {
        println "before nulling";        
        f = null;
        println "after nulling";
    }
}

def doSomethingMore() {
    println "doSomethingMore called"
    return "-wow";
}

println "output from call ---> " + doSomething()
0 голосов
/ 29 марта 2011

Блок finally всегда выполняется. http://download.oracle.com/javase/tutorial/essential/exceptions/finally.html Вот почему все три утверждения добавляются.

0 голосов
/ 29 марта 2011

Оператор finally всегда выполняется, поэтому возвращается строитель, а затем возвращается +1.

Во втором случае строитель имеет значение null, поэтому добавить к нему больше нечего.С таким же успехом это мог бы быть строитель = "" в последнем.

...