Java try,catch和finally块有助于编写可能在运行时引发异常的应用程序代码,并使我们有机会通过执行备用应用程序逻辑从异常中恢复,或者优雅地处理该异常以向用户报告。它有助于防止丑陋的应用程序崩溃。
1. Java尝试,捕获并最终阻止
1.1。尝试阻止
try块包含应在正常条件下运行的应用程序代码。例如,读取文件,写入数据库或执行复杂的业务操作。
尝试博克中使用try关键字,后跟花括号。
try {
//application code
}
|
1.2。捕获块
可选的catch块位于try块之后,并且必须处理try块引发的已检查异常以及任何可能的未检查异常。
try {
//code
}
catch (Exception e) {
//handle exception
}
|
应用程序可能会以N种不同方式出错。这就是为什么我们可以将多个catch块与一个try块相关联的原因。在每个catch块中,我们可以以一种独特的方式处理一个或多个特定的异常。
当一个catch块处理异常时,不执行下一个catch块。控制直接从已执行的catch块转移到执行程序的其余部分,包括finally块。
try {
//code
}
catch (NullPointerException e) {
//handle exception
}
catch (NumberFormatException e) {
//handle exception
}
catch (Exception e) {
//handle exception
}
|
1.3。终于封锁
一个可选的finally块使我们有机会在每次try-catch块完成时都运行我们要执行的代码-有错误或无错误。
即使我们未能在catch块中成功处理异常,也可以保证finally块语句的执行。
try {
//open file
//read file
}
catch (Exception e) {
//handle exception while reading the file
}
finally {
//close the file
}
|
1.4。仅try块是强制性的
请注意,只有try块是必需的,而catch和finally块是可选的。使用try块,我们可以根据需要使用catch块或finally块。
下面可能会在Java中同时给出两种组合。这两个版本均有效。
try {
}
catch (Exception e) {
}
|
try {
}
finally {
}
|
2. Java异常处理如何工作?
通常情况下,当运行时发生异常时,JVM会将错误信息包装在Throwable子类型的实例中。此异常对象类似于其他Java对象,并且具有字段和方法。
唯一的区别是JVM检查它们的存在并将控制权传递给catch
可以处理此异常类型或其父类类型的块。
尝试赶上终于流
当在应用程序中,找不到异常的catch块时,未捕获的异常由JVM级别的默认异常处理程序处理。它向用户报告异常并终止应用程序。
3.带有try,catch和finally块的不同执行流程
让我们看一些示例,以了解在不同情况下执行将如何进行。
3.1。尝试,捕获并最终阻止–没有发生异常
如果没有发生异常,那么JVM将仅执行finally块。捕获块将被跳过。
try
{
System.out.println( "try block" );
}
catch (Exception e)
{
System.out.println( "catch block" );
}
finally
{
System.out.println( "finally block" );
}
|
程序输出。
try block
finally block
|
3.2。尝试,捕获并最终阻止–发生异常
如果try块中发生异常,那么JVM将首先执行catch块,然后最后执行。
try
{
System.out.println( "try block" );
throw new NullPointerException( "Null occurred" );
}
catch (Exception e)
{
System.out.println( "catch block" );
}
finally
{
System.out.println( "finally block" );
}
|
程序输出。
try block
catch block
finally block
|
3.3。尝试并最终阻止–未处理异常
如果提供的catch块未处理该异常,则JVM默认异常处理程序将处理该异常。在这种情况下,将执行finally块,然后执行默认的异常处理机制。
try
{
System.out.println( "try block" );
throw new NullPointerException( "Null occurred" );
}
finally
{
System.out.println( "finally block" );
}
|
程序输出。
try block
finally block
Exception in thread "main"
java.lang.NullPointerException: Null occurred
at com.howtodoinjava.Main.main(Main.java: 12 )
|
3.4。尝试,捕获并最终阻止–多个捕获块
如果有多个与try块相关联的catch块,则异常由顺序处理的第一个catch块处理,可以处理异常类型或其父类型。
例如,处理IOException的catch块可以处理FileNotFoundException类型的异常,这也是因为FileNotFoundException extends IOException
。
try
{
System.out.println( "try block" );
throw new NullPointerException( "null occurred" );
}
catch (NumberFormatException e)
{
System.out.println( "catch block 1" );
}
catch (NullPointerException e)
{
System.out.println( "catch block 2" );
}
catch (Exception e)
{
System.out.println( "catch block 3" );
}
finally
{
System.out.println( "finally block" );
}
|
程序输出。
try block
catch block 2
finally block
|
3.5。尝试,捕获并最终阻止–捕获块引发异常
在catch块中处理另一个异常时,有时可能会有异常。它将如何处理?
如果catch块中有异常,则将执行转移到与各个catch块相关联的finally块(如果有)。然后,异常在方法调用堆栈中传播,以找到可以处理此异常的catch块。
如果找到了此类catch块,则将处理异常,否则JVM默认异常处理程序将处理该异常并终止应用程序。
try
{
System.out.println( "try block" );
throw new NullPointerException( "NullPointerException occured" );
}
catch (NullPointerException e)
{
System.out.println( "catch block 1" );
throw new NumberFormatException( "NumberFormatException occurred" );
}
catch (Exception e)
{
System.out.println( "catch block 2" );
}
finally
{
System.out.println( "finally block" );
}
|
程序输出。
try block
catch block 1
finally block
Exception in thread "main"
java.lang.NumberFormatException: NumberFormatException occurred
at com.howtodoinjava.Main.main(Main.java: 18 )
|
4.试用资源
对于可关闭资源(例如流),Java SE 7引入了try-with-resources语句,这是在上述情况下处理异常的推荐方法。在这种方法中,我们不需要关闭流,而JVM会为我们完成它。它消除了finally块的需要。
在try-with-resources中,资源在小括号内的try块中打开,最后该块完全消失了。
try (BufferedReader br = new BufferedReader( new FileReader( "C:/temp/test.txt" )))
{
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null )
{
System.out.println(sCurrentLine);
}
}
catch (IOException e)
{
e.printStackTrace();
}
|