之前面试时被问个问题,确实没有考虑过.
题目大意 : 当try、catch、finally中都存在return时,最后返回的为哪个的return值.
结论 :就上面的问题答案应该是finally中的return会覆盖掉try或catch中的return语句.
两篇很清楚的参照 :
原文 : Java finally语句到底是在return之前还是之后执行?
结论 :
finally块的语句在try或catch中的return语句执行之后返回之前执行且finally里的修改语句可能影响也可能不影响try或catch中 return已经确定的返回值,若finally里也有return语句则覆盖try或catch中的return语句直接返回。
原文 : finally块的问题(finally block does not complete normally)
结论 :
当finall块中包含return语句时,Eclipse会给出警告“finally block does not complete normally”,原因分析如下:
1、不管try块、catch块中是否有return语句,finally块都会执行。
2、finally块中的return语句会覆盖前面的return语句(try块、catch块中的return语句),所以如果finally块中有return语句,Eclipse编译器会报警告“finally block does not complete normally”。
3、如果finally块中包含了return语句,即使前面的catch块重新抛出了异常,则调用该方法的语句也不会获得catch块重新抛出的异常,而是会得到finally块的返回值,并且不会捕获异常。
结论,应避免在finally块中包含return语句。如果你在前面的语句中包含了return语句或重新抛出了异常,又在finally块中包含了return语句,说明你概念混淆,没有理解finally块的意义。
由两篇很清楚的参照,进行的测试,还涉及的由java只有值传递.
可以通过debug,更清楚的了解到具体的执行步骤,finally执行的时间.
public class FinallyReturn2 {
public static void main(String[] args) {
System.out.println("result b : " + findReturn2());
}
/**
* 测试在try中return执行之后,finally中内容是否执行
* 以及最终返回值为try中结果,或者为finally结果
*
* 根据debug的情况,说明try中的return是执行的,但同时执行之后仍然等待finally中代码的执行结果
*/
public static int findReturn2() {
int b = 0;
try {
System.out.println("try block.");
b++;
return b;
} catch (Exception e) {
System.out.println("catch block.");
} finally {
System.out.println("finally block.");
b++;
return b;
}
}
/*
* result :
* try block.
* finally block.
* result b : 2
* 结果 : 最终返回的结果为finally的结果.
* 结论 : 在try中存在return情况,finally仍会执行. 且执行时间是在try中return执行之后,返回之前.
* 且在finally中存在return的情况下,会直接覆盖try中返回.
*/
}
public class FinallyReturn3 {
public static void main(String[] args) {
System.out.println("result b : " + findReturn3());
}
/**
* 比较findReturn2,去掉了finally中的return
* 查看最后的返回结果是否为finally执行后的结果
* @return
*/
public static int findReturn3() {
int b = 0;
try {
System.out.println("try block.");
b++;
return b;
} catch (Exception e) {
System.out.println("catch block.");
} finally {
System.out.println("finally block.");
b++;
System.out.println("finally block b : " + b); // 执行finally后b的值
}
return b;
}
/*
* try block.
* finally block.
* finally block b : 2
* result b : 1
* 结果 : 最终返回的为try中return.
* 结论 : finally成功执行并更改了b的值,但此处并没有对try中的return值产生影响.
*/
}
import java.util.HashMap;
import java.util.Map;
public class FinallyReturn4 {
public static void main(String[] args) {
System.out.println("result map : " + findReturn4().get("key"));
}
/**
* 比较findReturn3,将2中的基础类型改为引用类型
* 查看最后返回结果是否为finally执行之后的结果 - (表明了java中是进行值传递).
*/
public static Map<String, String> findReturn4() {
Map<String, String> map = new HashMap<String, String>();
map.put("key", "init");
try {
System.out.println("try block.");
map.put("key", "try");
return map;
} catch (Exception e) {
System.out.println("catch block.");
} finally {
System.out.println("finally block.");
map.put("key", "finally");
System.out.println("finally block map : " + map.get("key"));
}
return map;
}
/*
* result :
* try block.
* finally block.
* finally block map : finally
* result map : finally
*
* 结果 : 最终仍返回try中return值 - debug单步执行表明
* 结论 : finally成功执行并更改了b的值,同时对try中的return值产生影响.
* 原因 : java中只有值传递,对于引用类型,try中return返回的为map的地址拷贝.
*/
}
import java.util.HashMap;
import java.util.Map;
public class FinallyReturn5 {
public static void main(String[] args) {
System.out.println("result map : " + findReturn5().get("key"));
}
public static Map<String, String> findReturn5() {
Map<String, String> map = new HashMap<String, String>();
map.put("key", "init");
try {
System.out.println("try block.");
map.put("key", "try");
return map;
} catch (Exception e) {
System.out.println("catch block.");
} finally {
System.out.println("finally block.");
map.put("key", "finally");
map = null; // 比较4中添加的语句,代码作用只是将map指向的引用变更为null
map.clear(); // 而非clear
}
return map;
}
/*
* result :
* try block.
* finally block.
* result map : finally
*/
}