Question

I saw one Java puzzle problem about finally, and return

    int i = 0;
    try {
        return i;
    } finally {
        i++;
    }

what's return value of this function, I know this will return 0, and I test another code

    StringBuffer sb = new StringBuffer("11");
    try {
        return sb;
    } finally {
        sb.append("22");
    }

it's strange things happend, it return "1122" this's my first question: why it return "1122"?

and I decompile the these two java code,

    0:   iconst_0 put 0 to the stack
1:   istore_0 store the stack top into index 0
2:   iload_0  put index 0 to the stack 
3:   istore_1 store the stack top into index 1
4:   iinc    0, 1 inc the index 0 with 1
7:   iload_1 put index 1 to the stack 
8:   ireturn return the top of stack
// what's the below bytecode mean? because the index 0 has incremented, why increment again?
9:   astore_2
10:  iinc    0, 1
13:  aload_2

this is my second question why 9 - 13 lines byte code means? and the index 0 has incremented, wy increment again?

   0:   new     #2; //class java/lang/StringBuffer
   3:   dup
   4:   ldc     #3; //String 11
   6:   invokespecial   #4; //Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
   9:   astore_0
   10:  aload_0
   11:  astore_1
   12:  aload_0
   13:  ldc     #5; //String 22
   15:  invokevirtual   #6; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
   18:  pop
   19:  aload_1
   // like the above, this seems should return the value in the index 1, it should be "11"??
   20:  areturn
   21:  astore_2
   22:  aload_0
   23:  ldc     #5; //String 22
   25:  invokevirtual   #6; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
   28:  pop
   29:  aload_2
   30:  athrow

this my third question, it seem the should be the value in the index, it should be "11"??

Was it helpful?

Solution

In the first example, 0 goes on the stack and is returned, regardless of what happens in the finally block.

In the second example, a reference to a StringBuffer goes on the stack, and then the StringBuffer itself is modified in the finally block. But the reference to the StringBuffer is unchanged, and that's what's returned.

OTHER TIPS

The behavior of the code and the first question can be explained without looking at the byte-code:

The code returns a StringBuffer object. The object is mutable and it is mutated in the finally block, which runs before execution is returned to the caller. (It still returns the same StringBuffer object.)

Try return sb.toString() (and change the return type to match) - in this case the side-effect to the StringBuffer won't affect the returned string object.

(I have no idea about the questions wrt the actual byte-code.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top