Why is printed 1?

半城伤御伤魂 提交于 2019-12-23 06:21:30

问题


I have code:

class Test {
  public static void main(final String [] args) {
    System.out.println(foo());
  }

  private static int foo() {
    int a = 0;
      try {
        ++a;
        return a;
      } finally {
        a = 10;
      }
    }
  }

I can't uderstand why 1 is printed.


回答1:


try {
    ++a;
    return a; // 1 is returned here
} finally {
    a = 10; // a is assigned with 10 later.
}

The value of a is incremented and returned in the try block itself. Post this return, the value of a is re-assigned in the finally block. And that is the reason, why it prints 1.


Quoting from the docs. This should help you understand it more clearly.

Compiling finally

Compilation of a try-finally statement is similar to that of try-catch. Prior to transferring control outside the try statement, whether that transfer is normal or abrupt, because an exception has been thrown, the finally clause must first be executed. For this simple example:

void tryFinally() {
    try {
        tryItOut();
    } finally {
        wrapItUp();
    }
}

The compiled code is:

Method void tryFinally()
0   aload_0             // Beginning of try block
1   invokevirtual #6    // Method Example.tryItOut()V
4   jsr 14              // Call finally block
7   return              // End of try block
8   astore_1            // Beginning of handler for any throw
9   jsr 14              // Call finally block
12  aload_1             // Push thrown value
13  athrow              // ...and rethrow value to the invoker
14  astore_2            // Beginning of finally block
15  aload_0             // Push this
16  invokevirtual #5    // Method Example.wrapItUp()V
19  ret 2               // Return from finally block
Exception table:
From    To      Target      Type
0       4       8           any

There are four ways for control to pass outside of the try statement:

  1. by falling through the bottom of that block
  2. by returning
  3. by executing a break or continue statement
  4. by raising an exception.



回答2:


This happens because the finally block of a try..catch..finally runs after the code within the try..catch has completed

You are assigned the value in finally and before that you returned in try

The code in finally always executes,but you are already returned the value in try.

try {
    ++a;
    return a; 
  } finally {
    a = 10; 
  }

Now a value is 10, after the return. Though not a good practice, Just for demo.

int a= 0;
try {
    ++a;
    return a; 
  } finally {
    a = 10;
    return a;
  }

Now it return's 10.

Edit:

Your doubt : Why unreacable error not coming ?

in try-catch-finally the blocks are different. Do the same in same block and see.

try {
            ++a;
            return a;
            a=100;  //compiler error.
          } finally {
            a = 10;
          }

Edit2

From java language specification of try-catch-finally :

A try statement executes a block. If a value is thrown and the try statement has one or more catch clauses that can catch it, then control will be transferred to the first such catch clause. If the try statement has a finally clause, then another block of code is executed, no matter whether the try block completes normally or abruptly, and no matter whether a catch clause is first given control.




回答3:


class Test {
  public static void main(final String [] args) {
    System.out.println(foo());
  }

  private static int foo() {
    int a = 0;
      try {
        ++a;
        return a;
      } finally {
        a = 10;
      }
    }
  }

In the above code, value returned will be 1 because, finally will not update the value returned in the try block.

class Test {
  public static void main(final String [] args) {
    System.out.println(foo());
  }

  private static int foo() {
    int a = 0;
      try {
        ++a;
        return a;
      } finally {
        a = 10;
    return a;
      }
    }
  }

The above code will return the value as 10, because, the value is returned from finally again.




回答4:


JVM is a stack-based machine. It push and pop value onto the stack. I decompiled Test class, to understand how it work.

private static int foo();
 Code:
   0: iconst_0        //push 0 to stack
   1: istore_0        //store 0 in the local variable 'a'(numbered 0). a==0
   2: iinc      0, 1  //increase the local variable 'a'(numbered 0) by 1. a==1;
   5: iload_0         //push value of the local variable 'a' onto the stack;
   6: istore_1        //store 1 in the local variable that not be declared(numbered 1);
   7: bipush    10    //push 10 onto the stack;
   9: istore_0        //store 10 in the local variable 'a'
  10: iload_1         //push onto stack value==1 of local variable that not be declared
  11: ireturn         //return 1
  12: astore_2
  13: bipush   10
  15: istore_0
  16: aload_2
  17: athrow
 Exception table:
 // not interesting ...



回答5:


Simply...you have not mentioned return a in or after final block. Final block is executed in the end and value of a is set to 10, but you have not coded to return this new value! Try below code to get your expected output:

class Test {
  public static void main(final String [] args) {
    System.out.println(foo());
  }

  private static int foo() {
    int a = 0;
      try {
        ++a;
        return a;
      } finally {
        a = 10;
       return a;
      }
    }
  }


来源:https://stackoverflow.com/questions/19651860/why-is-printed-1

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!