VextoR
VextoR

Reputation: 5165

try / finally block question

Found this question here

And I can't understand, why on first case it prints CoolReturn+1 and on second case CoolReturn? How does it work?

Thanks

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

What will be printed?

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");
    }
}

Answer: CoolReturn+1

A bit more difficult:

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;  /* ;) */
    }
}

Answer: CoolReturn

Upvotes: 7

Views: 751

Answers (7)

Sanjay T. Sharma
Sanjay T. Sharma

Reputation: 23208

This works because the return expression is evaluated before the finally block is executed. This is pretty apparent when you invoke a method in the return statement of your code and add logging statements to your try and finally blocks. The relevant explanation can be found in the JLS 3rd edition, 14.20.2. This is one of the reasons why return statements in the finally block produce a warning in IDE's like Eclipse.

A sample groovy code:

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()

Upvotes: 1

corsiKa
corsiKa

Reputation: 82559

The first one:

The finally will always fire (assuming the machien doesn't crash or anything). So after the return, the finally block fires, and since it has a reference to the object "builder", it appends the extra token to it.

The second one:

The finally block fires just like before, but it sets the reference to builder to be null. The object still exists, because it still has a link to it.

Upvotes: 6

Barend Venter
Barend Venter

Reputation: 476

In the first example, in the finally block, you manipulate the string builder with append.

In the second example, in the finally block, you change your pointer to the string builder to be the null pointer, after you return the result from the append method. This does not modify the string builder that you formerly pointed to in any way.

EDIT: Looks like I got beat to it.

Upvotes: 1

khachik
khachik

Reputation: 28693

Consider

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

as

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
    }
}

line 1 is executed, the builder is returned as result. Then line 3 is executed, and the builder gets appended by +1, then the ret is returned which is a "reference" to the object referenced by builder. The same is for the second case. Hope it is clear.

Upvotes: 7

TofuBeer
TofuBeer

Reputation: 61526

When it does return builder.append("Return") a copy of the reference to the builder variable is pushed onto the stack. Then builder is set to null. The caller then pops the copy of the reference off the stack.

Upvotes: 2

MBU
MBU

Reputation: 5098

The finally block will always execute. http://download.oracle.com/javase/tutorial/essential/exceptions/finally.html Thats why all three statements are appending.

Upvotes: 0

taylonr
taylonr

Reputation: 10790

The finally operator always runs so builder gets returned and then the +1 is returned.

On the second one, the builder is set to null, so there is nothing else to add to it. It could just as easily be builder = "" in the last one.

Upvotes: 0

Related Questions