Java Try Catch Final块没有Catch


125

我正在审查一些新代码。该程序仅具有try和finally块。由于不包含catch块,如果try块遇到异常或任何可抛出的异常,它将如何工作?它是否直接进入了finally块?



25
@mP每个人都应该进行代码审查,并向他们提问如何学习和改进。
卡尔·普里切特

Answers:


130

如果try块中的任何代码都可以引发已检查的异常,则它必须出现在方法签名的throws子句中。如果引发了未经检查的异常,则该异常会冒泡退出方法。

无论是否引发异常,都始终执行finally块。


11
第一段不一定正确。尝试块可以嵌套。任何未捕获的异常(无论是否选中)都将冒出该方法。
安迪·托马斯

4
可以嵌套尝试块,但我不建议这样做。我不会那样写代码。
duffymo 2010年

2
@duffymo:“冒出方法”是什么意思?
今天我

5
@Anand只是一些非技术性的语言,用于“引发异常”。
duffymo

2
不容忽视;传递方法链。
duffymo '16

93

关于try/ 的小提示finally

  • System.exit() 叫做。
  • JVM崩溃。
  • try{}块永远不会结束(例如无限循环)。

4
try{..} catch{ throw ..} finally{..}呢 我认为最终不会被执行
sbeliakov

10
在那种情况下,最后仍然会被调用。仅原始异常丢失。
彼得·劳瑞

如果您之前调用System.exit(),则最后也不会执行。
mmirror,

2
@jyw这就是上面列表中第一项的意思。
彼得·劳瑞

我不得不说,这涵盖了所有基础!
奥斯卡·布拉沃

39

Java语言规范(1)描述了如何try-catch-finally执行。没有捕获等于没有捕获能够捕获给定Throwable的捕获。

  • 如果由于抛出值V而使try块的执行突然完成,则可以选择:
    • 如果V的运行时类型可分配给try语句的任何catch子句的参数,则
      ……
    • 如果V的运行时类型不能分配给try语句的任何catch子句的参数,则执行finally块。然后有一个选择:
      • 如果finally块正常完成,则try语句由于抛出值V而突然完成。
      • 如果final块由于原因S突然完成,则try语句由于原因S突然完成(并且值V的抛出被丢弃并忘记了)。

(1)最终执行try-catch


16

内部的finally在将异常抛出到外部的块之前执行。

public class TryCatchFinally {

  public static void main(String[] args) throws Exception {

    try{
        System.out.println('A');
        try{
            System.out.println('B');
            throw new Exception("threw exception in B");
        }
        finally
        {
            System.out.println('X');
        }
        //any code here in the first try block 
        //is unreachable if an exception occurs in the second try block
    }
    catch(Exception e)
    {
        System.out.println('Y');
    }
    finally
    {
        System.out.println('Z');
    }
  }
}

结果是

A
B
X
Y
Z

6

无论try正常结束还是由于异常(可抛出)而异常结束,finally块始终在try块结束后运行。

如果try块中的任何代码都引发了异常,则当前方法仅在运行finally块之后简单地重新引发(或继续引发)相同的异常。

如果finally块抛出异常/错误/抛出,并且已经存在未决的抛出,那么它将变得很丑陋。坦率地说,我确实忘记了会发生什么(很多年前对我的认证来说)。我觉得两个可投掷物品都链接在一起,但是在“最终”呕吐,呕吐之前,您必须要做一些特殊的伏都教(即,我必须查询一个方法调用)才能解决原始问题。

顺便说一句,try / finally是资源管理中很常见的事情,因为java没有析构函数。

例如-

r = new LeakyThing();
try { useResource( r); }
finally { r.release(); }  // close, destroy, etc

“最后”,还有一个提示:如果您不愿意放入catch,则可以捕获特定的(预期的)throwable子类,或者只是捕获“ Throwable” 而不是 “ Exception”,以获取通用的通用错误陷阱。太多问题,例如反射钉,抛出“错误”,而不是“异常”,并且这些问题会因编码为“ catch all”的所有内容而直接消失:

catch ( Exception e) ...  // doesn't really catch *all*, eh?

改为这样做:

catch ( Throwable t) ...

丑陋的部分,请参见下面的Carlos Heuberger的回答。
mplwork

3

Java版本7之前的版本允许try-catch-finally这三种组合...

try - catch
try - catch - finally
try - finally

finally无论tryor或and catch块中发生了什么,都将始终执行block。因此,如果没有catch块,则不会在此处处理异常。

但是,您仍然需要在代码中的某个地方使用异常处理程序-除非您当然希望应用程序完全崩溃。它取决于处理程序所在位置的应用程序体系结构。

  • Java try块之后必须是catch或finally块。
  • 对于每个try块,可以有零个或多个catch块,但只有一个finally块。
  • 如果程序退出(通过调用System.exit()或导致导致进程中止的致命错误),则不会执行finally块。

1
“版本7之前允许”是指Java 7和Java 8不允许这三种组合吗?我怀疑那是您的意思,但这就是您的答案所暗示的。
Loduwijk

如果try块中有return语句,则执行finally块吗?
拉胡尔·亚达夫

@Rahul是的,最后会被叫到。参考:stackoverflow.com/questions/65035/…–
roottraveller

1
@Aaron-try-with-resource的新语法,它自动在try关键字之后的parens中构造的任何内容上调用.close()。
Roboprog

2

如果try块遇到异常或任何可抛出的异常,它将如何工作

就像其他任何未捕获到的异常一样,该异常也被抛出该块。

无论try块如何退出,都将执行finally块-不管是否有任何catch,无论是否有匹配的catch。

catch块和finally是try块的正交部分。您可以拥有一个或两个。使用Java 7,您将一无所获!



1

try块完成后,将执行finally块。如果try块离开时在try块内抛出了某些东西,则执行finally块。


0

try块内部,我们编写了可能引发异常的代码。该catch块是我们处理异常的地方。finally无论是否发生异常,始终执行该块。

现在,如果我们有try-finally块而不是try-catch-finally块,则不会处理该异常,并且在try块而不是控制要捕获的块之后,它将进入finally块。当我们不希望发生任何异常时,可以使用try-finally块。


0

无论是否在try块中引发异常,finally都将执行块。不会捕获异常。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.