鉴于此代码:
String test() {
try {
return "1";
} finally {
return "2";
}
}
语言规范是否定义了调用的返回值test()
?换句话说:在每个 JVM 中它总是相同的吗?
在 Sun JVM 中,返回值为2
,但我想确定,这不是 VM 相关的。
是的,语言规范定义“2”是结果。如果 VM 以不同的方式执行此操作,则它不符合规范。
大多数编译器都会抱怨它。例如,Eclipse 会声称 return 块永远不会被执行,但这是错误的。
编写这样的代码是非常糟糕的做法,永远不要这样做:)
是的,Java 语言规范在这个问题上非常清楚(14.20.2):
通过首先执行 try 块来执行带有 finally 块的 try 语句。然后有一个选择:
- 如果 try 块的执行正常完成,则 [...]
- 如果由于抛出值 V 而导致 try 块的执行突然完成,则 [...]
- 如果 try 块的执行由于任何其他原因 R 突然完成,则执行 finally 块。然后有一个选择:
- 如果 finally 块正常完成,[...]
- 如果 finally 块由于原因 S 突然完成,则 try 语句由于原因 S 突然完成(并且原因 R 被丢弃)。
finally 块将始终执行,但以下示例除外:
String test() {
try {
System.exit(0);
} finally {
return "2";
}
}
在这种情况下,JVM 将停止,而不执行该finally
块。
因此,在您的示例中,返回值将是2
.
是的,如果您从finally
块中返回某些内容,它将替换您可能从try
orcatch
块中返回的任何内容。
例外情况也是如此。如果你在finally
块中抛出一些东西,该异常将替换在try
orcatch
块中抛出的任何异常。所以要小心,永远不要在finally
块中扔东西,因为它可能会隐藏失败的原始原因。
阅读程序的ByteCode后,代码如下:
finally 块语句内联在 try 块的 return 语句之前,因此 finally 块的 return 将首先执行,而原始的 return 语句永远不会执行。
对于程序:
String test() {
try {
System.out.println("try");
return "1";
} finally {
System.out.println("finally");
return "2";
}
}
它转换为:
String test()
{
System.out.println("try");
String s = "1"; //temporary variable
System.out.println("finally");
return "2";
Exception exception;
exception;
System.out.println("finally");
return "2";
}
对于程序:使用catch 块:
String test() {
try {
System.out.println("try");
return "1";
} catch (RuntimeException e) {
System.out.println("catch");
return "2";
} finally {
System.out.println("finally");
return "3";
}
}
转换为:
String test()
{
System.out.println("try");
String s = "1";
System.out.println("finally");
return "3";
RuntimeException e;
e;
System.out.println("catch");
String s1 = "2";
System.out.println("finally");
return "3";
Exception exception;
exception;
System.out.println("finally");
return "3";
}
注意:使用 JDK 1.7 编译并使用 Cavaj 反编译。
您可以参考以下链接。我希望它能提供所有细节:
http://www.programmerinterview.com/index.php/java-questions/will-finally-run-after-return/
它说 finally 块将始终执行,即使 try 或 catch 块有返回语句。如果 finally 块也有 return 语句,那么这将覆盖 try 或 catch 块内的 return 语句,在这种情况下,try/catch 中抛出的任何异常都将被丢弃(不好的方法)。
上面的答案总结得很好,只是想在这里再补充一点。
private static int divide(int a , int b){
try{
return a/b;
}finally{
System.out.println("In finally");
return 1;
}
}
如果我们传递 1,0 那么上面的方法将抑制它抛出的异常并返回结果。有人说过,上面的代码不应该在生产环境中使用。
private static int divide(int a , int b){
int result = 0;
try{
result = a/b;
}finally{
System.out.println("In finally");
result = 1;
}
return result;
}
在 finally 块之后使用 return 语句将导致
Exception in thread "main" java.lang.ArithmeticException: / by zero