会。finally块总会执行,即使try中有return;JVM先暂存return值,再执行finally,最后返回暂存值;若finally含return则覆盖原返回值,否则仅做清理。
会。只要finally块存在且未被System.exit()或JVM崩溃等极端情况中断,它就一定会执行——哪怕try块里写了return。
关键在于:不是“先return再finally”,而是“先暂存return值,再执行finally,最后返回那个被暂存的值”。这导致一个常见误解:以为finally里改了变量就能改变返回值——对基本类型和不可变对象(如String)无效;对可变对象(如StringBuilder、自定义对象)可能生效,但属于危险操作,不推荐依赖。
只有当finally块自身也包含return语句时,它才会真正覆盖try或catch中的return。此时,try里的return会被完全丢弃,程序直接从finally返回。
finally中无return:原return值被保留,finally仅做清理finally中有return:立即返回,跳过try/catch中已计算但未送出的返回值finally抛出异常:该异常会“吞掉”try中的return,调用方收到的是finally的异常public static int test() {
try {
return 1;
} finally {
return 2; // 实际返回2,1被丢弃
}
}
这不是语法错误,但属于严重逻辑陷阱:
finally强行截断try抛了异常,finally的return会让异常彻底消失finally只做资源释放,突然返回值会引发维护困惑Java官方文档明确建议:不要在finally中使用return、throw或break等转移控制流的语句。
把清理逻辑和返回逻辑分离。需要“执行后返回”的场景,优先用显式变量承载结果,确保控制流清晰:
public static String readFile(String path) {
BufferedReader reader = null;
String content = null;
try {
reader = new BufferedReader(new FileReader(path));
content = reader.readLine();
return content; // 明确在此决定返回什么
} catch (IOException e) {
return null;
} finally {
if (reader != null) {
try {
reader.close(); // 只做清理,不碰return
} catch (IOException ignored) {}
}
}
}
复杂点在于:return值的计算时机、finally对可变对象的副作用、以及JVM字节码层面的“暂存-执行-送出”三阶段模型。这些细节一旦忽略,调试时很容易误判执行顺序。