我正在审查一些新代码。该程序只有一个 try 和一个 finally 块。由于排除了 catch 块,如果 try 块遇到异常或任何可抛出的东西,它是如何工作的?它只是直接进入finally块吗?
11 回答
如果 try 块中的任何代码可以抛出已检查异常,则它必须出现在方法签名的 throws 子句中。如果抛出未经检查的异常,它就会从方法中冒出来。
finally 块总是被执行,无论是否抛出异常。
关于try
/的一个小提示finally
:finally 将始终执行,除非
System.exit()
叫做。- JVM 崩溃。
- 块永远不会结束(
try{}
例如无限循环)。
Java 语言规范(1)描述了如何try-catch-finally
执行。没有捕获相当于没有捕获能够捕获给定的 Throwable。
- 如果 try 块的执行由于抛出值 V 而突然完成,那么有一个选择:
- 如果 V 的运行时类型可分配给 try 语句的任何 catch 子句的参数,则 ...<br> ...
- 如果 V 的运行时类型不可分配给 try 语句的任何 catch 子句的参数,则执行 finally 块。然后有一个选择:
- 如果 finally 块正常完成,那么 try 语句会因为抛出值 V 而突然完成。
- 如果 finally 块由于原因 S 突然完成,则 try 语句由于原因 S 突然完成(并且值 V 的抛出被丢弃并被遗忘)。
内部 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
finally 块总是在 try 块结束后运行,无论 try 正常结束还是由于异常而异常结束,呃,throwable。
如果 try 块中的任何代码抛出异常,则当前方法只是重新抛出(或继续抛出)相同的异常(在运行 finally 块之后)。
如果 finally 块抛出异常 / 错误 / throwable,并且已经有一个待处理的 throwable,它会变得很丑。坦率地说,我完全忘记了发生了什么(对于我多年前的认证而言)。我认为这两个 throwable 都连接在一起,但是您必须做一些特殊的巫术(即 - 我必须查找的方法调用)才能在“最终”被吐出之前解决原始问题,呃,吐出。
顺便说一句,try/finally 对于资源管理来说是一件很常见的事情,因为 java 没有析构函数。
例如 -
r = new LeakyThing();
try { useResource( r); }
finally { r.release(); } // close, destroy, etc
“最后”,还有一个提示:如果您确实费心放入一个 catch,要么捕获特定的(预期的)可抛出的子类,要么只捕获“Throwable”,而不是“Exception”,以获得一般的捕获所有错误陷阱。太多的问题,例如反射错误,抛出“错误”,而不是“异常”,并且这些问题将被任何“捕获所有”编码为:
catch ( Exception e) ... // doesn't really catch *all*, eh?
改为这样做:
catch ( Throwable t) ...
版本 7 之前的 Java 版本允许try-catch-finally的这三种组合......
try - catch
try - catch - finally
try - finally
finally
无论try
or/andcatch
块中发生了什么,块都将始终执行。所以如果没有catch
阻塞,这里就不会处理异常。
但是,您仍然需要在代码中的某处使用异常处理程序——当然,除非您希望您的应用程序完全崩溃。这取决于您的应用程序的体系结构,该处理程序的确切位置。
- Java try 块必须后跟 catch 或 finally 块。
- 对于每个 try 块,可以有零个或多个 catch 块,但只有一个 finally 块。
- 如果程序退出(通过调用 System.exit() 或通过导致导致进程中止的致命错误),将不会执行 finally 块。
如果遇到异常或任何可抛出的东西,try 块如何工作
异常被抛出块外,就像在任何其他没有被捕获的情况下一样。
无论 try 块如何退出,都将执行 finally 块——无论是否有任何捕获,无论是否有匹配的捕获。
catch 块和 finally 块是 try 块的正交部分。你可以有一个或两个。使用 Java 7,您将无法拥有这两者!
你不试试那个程序吗?它将转到 finally 块并执行 finally 块,但是不会处理异常。但是,该异常可以在 finally 块中被否决!
finally 块在 try 块完成后执行。如果在 try 块离开时抛出了某些东西,则执行 finally 块。
在try
块内部,我们编写可以引发异常的代码。该catch
块是我们处理异常的地方。finally
无论是否发生异常,该块总是被执行。
现在如果我们有 try-finally 块而不是 try-catch-finally 块,那么异常将不会被处理,并且在 try 块而不是控制去 catch 块之后它将进入 finally 块。当我们不想对异常做任何事情时,我们可以使用 try-finally 块。
无论是否在try
块中抛出异常 -finally
都会执行块。异常不会被捕获。