我有以下代码:
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
答案 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)
会发生以下情况:
答案 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。