Java try..catch&最后

时间:2013-09-06 07:41:38

标签: java exception try-catch

我有以下代码:

public class test3    
{
    public static void main(String a[])
    {
        System.out.println("In main");
        System.out.println(new Demo(0).devide());    
    }
}
class Demo
{
    int x;
    Demo(int x)
    {
        this.x=x;
    }
    public int devide()
    {   
        try
        {
            return x/x;
        }
        catch(Exception e)
        {
            System.out.println(e);
            return 4;

        }
        finally
        {
            System.out.println("In finally");
            return 1;
        }    
    }
}

在上面的代码中,我希望4作为输出,但生成的输出是:

In main
java.lang.ArithmeticException: / by zero
In finally
1

所以它返回1

7 个答案:

答案 0 :(得分:2)

最后总是在退出try / catch块之前调用,即使catch返回。实际上,return中的finally优先于catch中的返回,catch中的返回永远不会发生。有关详细信息和说明,请参阅here

基本上,归结为它转换为字节码的方式。 finally中的代码被视为“子过程”,并且在每个出口点,在离开try / catch块之前,对代码执行jsr跳转在finally。由于子过程跳转不是真正的过程调用,return中的finally禁止从子过程返回到输入它的点,因此永远不会执行原始return

divide()到字节码的粗略翻译可能如下所示:

    aload_0
    getfield   // x
    dup
    idiv
    istore_1
    jsr        // to finally block
    iload_1
    ireturn

// catch
    bipush 4
    istore_1
    jsr        // to finally block
    iload_1
    ireturn

// finally
    astore_2   // save the return address
    bipush 1
    ireturn
    ret 2      // dead code

在那里我们可以清楚地看到为什么是从未执行过的catch返回。

答案 1 :(得分:2)

finally
{

}
无论之前执行的是什么其他代码,

都将被执行

所以,最后它会返回1,这实际上是你没想到的:)

答案 2 :(得分:2)

会发生以下情况:

  1. 代码到达返回4;
  2. 将值4放在返回堆栈上
  3. 代码到达返回1;
  4. 将值1放在返回堆栈上
  5. 方法结束,返回堆栈顶部(因此值1),并丢弃值4。

答案 3 :(得分:1)

根据 JLS 14.20.2。执行try-finally和try-catch-finally:

  

如果try块的执行由于值throw的{​​{1}}突然完成,则可以选择:

     

如果V的运行时类型与V语句的任何catch子句的可捕获异常类兼容,则第一个(最左侧){{1} }子句被选中。将值try分配给所选catch子句的参数,并执行该V子句的块。然后有一个选择:

     

如果catch块正常完成,则执行catch块。

答案 4 :(得分:1)

finally块总是被激活,总是如此。好吧,如果你在System.exit(0)中拨打try,也可能不会。但在其他情况下 - 无论try / catch如何退出(正常或突然)。

finally的返回值(如果指定的话)覆盖了try / catch的返回值。同样适用于异常 - 来自try / catch的异常会被丢弃,如果最终抛出它自己的异常。

答案 5 :(得分:0)

在这种情况下,4也会添加到stack,但在最终运行后,这将返回1。因此,您只能看到1,因为1是堆栈的顶部元素。

检查出来

 try
    {
        return x/x;
    }
    catch(Exception e)
    {
        System.out.println(e);
        x=4;
        return x++;


    }
    finally
    {
        System.out.println("In finally");
        return x;
    }

你能看到什么

    In main
    java.lang.ArithmeticException: / by zero
    In finally
    5

现在你可以实现catch并最终返回值,但是我们可以看到堆栈中的top元素。

答案 6 :(得分:0)

如果你的程序执行控制被输入try块,那么最后执行块。不管try块是否会在没有任何异常或任何异常的情况下执行,或者在try块中你使用return语句JVM将始终执行finally块,然后终止你的程序。 例如:

 public class test3    
{
    public static void main(String a[])
    {
        System.out.println("In main");
        System.out.println(new Demo(10).devide());    
    }
}
class Demo
{
    int x;
    Demo(int x)
    {
        this.x=x;
    }
    public int devide()
    {   
        try
        {
            return x/x;
        }
        catch(Exception e)
        {
            System.out.println(e);
            return 4;

        }
        finally
        {
            System.out.println("In finally");
            return 1;
        }    
    }
}

上面的pgm将在没有任何异常的情况下执行,但最后仍会执行block。