Logo

郎哥编程

finally语句

2019-12-25 202

如果try语句块中存在异常,则异常之后的代码将不再执行。但在某些特定的情况下,不管是否有异常发生,总是要求某些特定的代码必须被执行。例如,程序中执行数据库连接的代码,不管对数据库的操作是否成功,最后都要关闭数据库的连接以释放内存资源,这就需要用到finally语句。

finally语句的语法规则如下:

try {
    //代码段(可能发生异常的代码)
} catch( 异常类型 ex ) {
    //对异常进行处理的代码
} finally {
   //总要被执行的代码
}
//代码段

 案例1:建立FinallyDemo类,演示finally的用法。

在throwdemo包下新建FinallyDemo类。代码如下:

public class FinallyDemo {
 
    /** 
    * @Title: main 
    * @Description: Java程序入口main方法
    * @param @param args    参数 
   
    * @return void    返回类型 
    * @throws 
    */
 
    public static void main(String[] args) {
       System.out.println("请打开数据库连接。。。。。。");
       try {
           System.out.println("执行查询操作");
           System.out.println("执行修改操作");
           // 发生除零异常
           int  i= 12/0;
           System.out.println("执行添加操作");
           System.out.println("执行删除操作");
       } catch(Exception ex) {
           System.out.println("除零出错!");
           ex.printStackTrace();
       } finally {
           // 不管异常是否发生,该语句都会执行
           System.out.println("请关闭数据库连接......");
       }
 
    }
 
}

代码为了演示finally语句的效果,在try语句块中设置了除零异常。当代码执行到语句i= 12/0时,程序抛出异常。控制台显示结果如下图所示:

image.png                                             

从上面的代码可以看出,无论是否出现异常,都不会影响到finally语句的执行。不管try是以何种方式结束的(正常结束、异常结束、通过return或break控制流语句结束),finally语句也总是恰好在成员函数返回前执行。

案例2:建立ReturnExceptionDemo类,演示return语句和finally语句先后执行顺序。

在throwdemo包下新建ReturnExceptionDemo类。代码如下:

package throwdemo;
 
/** 
* @ClassName: ReturnExceptionDemo 
* @Description: 异常处理(finally语句)案例2 
* @author 编程训练营 
* @date 
* 
*/
 
public class ReturnExceptionDemo {
 
    /**
     * @Title: main
     * @Description: Java程序入口main方法
     * @param args 参数
     *
     * @return void 返回类型 @throws
     */
 
    public static void main(String[] args) {
 
       try {
           methodA();
       } catch (Exception e) {
           System.out.println(e.getMessage());
       }
       methodB();
 
    }
   
    /** 
    * @Title: methodA 
    * @Description: 方法A
    * @param     参数 
   
    * @return void    返回类型 
    * @throws 
    */ 
    static void methodA() {
          try {
           System.out.println("进入方法A");
           //抛出异常
           throw new RuntimeException("制造异常");
         } finally {
            //该语句不管发生什么都会执行
            System.out.println("执行A方法的finally");
         }
       }
      
       /** 
    * @Title: methodB 
    * @Description: 方法B
    * @param     参数 
   
    * @return void    返回类型 
    * @throws 
    */ 
    static void methodB() {
         try {
           System.out.println("进入方法B");
           //返回,实际上是在finally语句执行完后才返回
           return;
         } finally {
            //该语句不管发生什么都会执行
            System.out.println("执行B方法的finally");
        }
    }
 
}

运行程序,输出结果如下图所示:

image.png


从输出结果可以看出,不管什么情况下,finally语句都会被执行。

在代码methodB方法try语句块中,程序执行到return语句时,程序会产生一个局部展开,finally语句块的代码会被插入到return语句之前执行。不过注意的是,finally语句块的代码虽然在return语句之前执行,但是finally语句块的代码不能够通过重新赋值的方式来改变return语句的返回值。

案例3:建立TestFinallyReturn类,测试是否能通过finally语句来改变return语句的返回值。

在throwdemo包下新建TestFinallyReturn类。代码如下:

package throwdemo;
 
/** 
* @ClassName: TestFinallyReturn 
* @Description: 异常处理(finally语句)案例3
* @author 编程训练营 
* @date 
* 
*/
 
public class TestFinallyReturn {
 
    /** 
    * @Title: main 
    * @Description: Java程序入口main方法
    * @param @param args    参数 
   
    * @return void    返回类型 
    * @throws 
    */
 
    public static void main(String[] args) {
       //你认为testFinally方法返回的值是多少呢?
       System.out.println("testFinally返回的值为:" + testFinally());
 
    }
   
    public static int testFinally()
    {
       int temp = 1;
       try {
           // 返回temp的值
           return temp;
       } catch(Exception e) {
           e.printStackTrace();
       } finally {
           // temp赋值为2
           temp = 2;
       }
       return 0;
    }
 
 
}

案例代码中,本来是想在finally语句块中通过改变temp的值,来影响testFinally方法最终返回值,但是真的影响了吗?程序输出结果如下图所示:

image.png


从上图可以看出,testFinally方法并没有返回我们需要的值。虽然finally语句块的代码不会影响try语句块中return语句的返回值。但是可以在finally内部使用return语句。如果把上列的finally语句块的代码改为如下所示:

public static int testFinally()
{
    int temp = 1;
    try {
        return temp;
    } catch(Exception e) {
        e.printStackTrace();
    } finally {
        temp = 2;
        return temp;
    }
    return 0;
}

由于finally语句块的代码优于return语句执行,如果此时在finally语句块中内部也有return语句,这将会导致该方法直接返回,而使try语句块中的return语句得不到执行机会,所以返回结果为2。

对上述情况,其实更合理的做法是,既不在try语句块中使用return语句,也不在finally语句块中使用return语句,而应该在finally语句块之后使用return语句来表示方法的结束和返回。修改后的代码如下:

public static int testFinally()
{
    int temp = 1;
    try {
        //操作语句
    } catch(Exception e) {
        e.printStackTrace();
    } finally {
        temp = 2;
    }
    return temp;
}

 finally语句一般和try......catch......连用,用来做一些善后清理工作,可以把文件关闭,关闭数据库连接等操作放置到finally语句块内,避免程序出现异常时,不能及时执行关闭文件等释放系统资源操作。


代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论