0

我有以下代码:

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

4

8 回答 8

2

发生的情况如下:

  1. 代码达到返回 4;
  2. 值 4 被放入返回堆栈
  3. 代码到达返回 1;
  4. 值 1 被放入返回堆栈
  5. 方法结束,返回栈顶(因此值为 1)并丢弃值 4。
于 2013-09-06T07:45:18.653 回答
2

finally 总是在退出try/catch块之前调用,即使catch返回。实际上,returninfinally先于 in 的返回catch,并且 in 的返回catch永远不会发生。有关详细信息和说明,请参见此处

基本上,它归结为它被翻译成字节码的方式。代码 infinally被视为“子过程”,并且在每个退出点,就在离开try/catch块之前,jsr执行跳转到代码 in finally。由于子过程跳转不是真正的过程调用,returninfinally禁止从子过程返回到它进入的点,因此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 中的 return 从未执行过。

于 2013-09-06T07:44:33.467 回答
2
finally
{

}

不管之前是否执行了其他代码,最终都会被执行

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

于 2013-09-06T07:45:00.680 回答
1
In above code I expect 4 as output but output generated is :
In main
java.lang.ArithmeticException: / by zero
In finally
1

你期待什么?

除非 JVM 崩溃或您之前调用 System.exit(),否则将始终执行 finally 块。由于您在 finally 块中返回 1,因此您将获得 1 作为输出。

于 2013-09-06T07:45:43.260 回答
1

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

如果块的执行由于 a的值try而突然完成,那么有一个选择:throwV

如果运行时类型是与语句的任何子句的V可捕获异常类兼容的赋值,则选择第一个(最左边)这样的子句。该值被分配给所选子句的参数,并执行该子句的块。然后有一个选择:catchtrycatchVcatchcatch

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

于 2013-09-06T07:46:14.783 回答
1

finally块总是被执行,总是。好吧,也许如果你打电话System.exit(0)try它就不会了。但在其他情况下,它是 - 无论try/是如何catch退出(通常或突然)。

(如果您指定它)的返回值finally覆盖来自 try/catch 的返回值。异常也是如此——如果最终抛出自己的异常,try/catch 中的异常就会被丢弃。

于 2013-09-06T07:59:38.913 回答
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

现在您可以同时实现捕获和最终返回值,但是我们可以看到堆栈中的顶部元素。

于 2013-09-06T07:46:40.490 回答
0

如果您的程序执行控制进入 try 块,则执行 finally 块。无论 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 将毫无例外地执行,但 finally 块仍将执行。

于 2013-09-06T07:58:27.747 回答