try{} finally{} construct with return values
我想知道为什么Java编译器会接受下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Main {
public static void main (String ... args){
System. out. println("a() =" + a ());
}
public static String a (){
try {
return"a";
}catch(Throwable t ){
}finally{
return"b";
}
}
} |
这可以也不应该奏效。Java规范说明EDCOX1的"0"块将始终被执行,但同时返回值已经被指定。所以要么你不能执行return"b"语句,因为你已经在return"a"退出,这是不正确的。
但是,另一种选择是执行return"b"语句,从而完全忽略return"a"语句…
我会说这两个都是错误的,我希望这不会编译。但是它编译和运行良好。我会把答案留给读者作为一个很好的练习。
基本上,我的问题是:除了做不好的练习之外,这会被认为是Java错误,还是除了混淆之外还有其他的妙用呢?
编辑:
如果问题是一个已经被回答的bug,那么问题就不那么多了,但是它有好的用例吗?
- 这个问题是我这周读到的最有趣的问题之一。然而,据我所知,try块永远不会抛出异常。
- 非常意外的输出!!
- 这个问题有很多重复。stackoverflow.com/questions/65035/…stackoverflow.com/questions/4185340/…stackoverflow.com/questions/19899155/……
- finally块有权覆盖任何返回值。所以您的代码应该返回"B"。
- @希哈莫夫,这个输出中有什么是意外的?
- @你说得对。我刚尝试过,intellij报告"finally"块不能正常完成,"return"在"finally"块内:虽然偶尔会出现这种返回语句,但这种返回语句可能会掩盖抛出的异常,并使调试极其复杂。
- @实际上,我的智能根本没有警告我。
- 我觉得这是一个有趣的问题,我从来没有听说过有人用回程在最后一个街区。我个人认为这是一个错误,更多的是一个不好的实践。另一件事是,正如我所记得的,最后一个块并不总是被执行,如果我记得如果你调用System.exit它想要被执行
- @Christophedetroyer您引用的大多数副本都没有提到返回值
- 1)"大部分"足以复制。2)它们都解释了语义。不需要这个问题。
- @很有趣。我得到三个警告,也许你已经禁用了一些通常启用的或相反的方法…
- @Christophedetroyer请给我一个问题,它要求一个用例-)。修改了我的问题以强调这一部分。
- @尤里——要求一个用例会使这个话题偏离主题,因为它往往会吸引固执己见的答案,这是一个不同的结束原因。这是一个问答网站-应该有明确的问题答案,而不是意见。我投票决定不公开。
一切都按预期工作,这里没有错误。当您有疑问时,JLS是您的救世主:
JLS-14.20.2.Try Finally和Try Catch Finally的执行:
If execution of the try block completes abruptly for any other
reason R, then the finally block is executed, and then there is a
choice:
-
If the finally block completes normally, then the try statement
completes abruptly for reason R.
-
If the finally block completes abruptly for reason S, then the try
statement completes abruptly for reason S (and reason R is
discarded).
号
它覆盖try块中的值。
return中的finally丢弃了try子句中可以抛出的所有异常。
- 好的,所以没有错误。谢谢,但是用例呢
- @尤里,我真的想不出有什么有用的情况。
- 因此,在这种情况下,这只是一个奇怪的设计决策:—)
- @尤里想到一种情况,你有一个something = null; try { run = tryThis(); } finally { cleanThings(); return something; },如果你想返回null作为一个默认值,如果发生了什么不好的事情。
- @如果发生了什么不好的事情,Marounmaroun?它总是返回空值。
- @汤姆,你说得对,但这不会清理东西的。也许我已经不想再去寻找有用的案例了;)
- @marounmaroun well,一个用例是,finally中的返回总是返回一个特定的值,无论是否发生异常。因此,您不必在try和每个catch块中编写返回语句。但我不认为这是设计决策的主要原因。
- 想想这个:int a=3; try{ return ++a; }catch(..){}finally{ return ++a; },这不是很棒吗?
- @尤里,为什么这会有用?
- @尤里,这有什么了不起的?
- @汤姆,它返回5;)
- @尤里·洛尔……
- @尤里·埃多克斯(YuriEDOCX1)(6)也这样做。
- @汤姆,你不擅长代码混淆,是吗?;-)开玩笑的是,我有点讽刺这种结构的完全无用。