Java 进阶6 异常处理的陷阱 20131113
异常处理机制是 Java语言的特色之一,尤其是 Java的Checked 异常,更是体现了 Java语言的严谨性:没有完善的错误的代码根本就不会被执行。对于 Checked异常,Java 程序要么声明抛出,要不使用 try .. catch捕获程序运行过程中抛出的异常,进行处理。 Java开发程序员都是无法回避异常处理的情况, Java异常处理同样存在着一些迷惑的地方。例如在 finally代码块执行的规则是怎样的?程序中遇到 return语句之后还会执行finally代码块吗?程序遇到 System.exit()的时候还会执行finally代码块吗?
1. 正确关闭资源的方式
          实际的开发过程中经常需要打开一些物理资源,比如数据库连接、网络连接、磁盘文件等等,打开这些资源的之后必须要显式的关闭资源,否则会引起资源的泄漏。虽然 JVM有垃圾回收机制,但是对于这些资源, JVM是不会回收这些资源的, JVM只能够回收内存,而不能回收资源。
          传统的方式关闭资源,在 finally中
         finally{
         oos.close();ois.close(); 回收资源,但是这种方式不一定是安全的,因为在 oos ois未初始化的时候,程序运行就发生异常的话,那么 oos和ois 为完成初始化,这样的话, oos和ois 是没有必要关闭的。所以使用下面的方式关闭资源的话,是一种相对稳妥的方式。也就是在关闭之前,判断这些资源是否是有效的。
}
finally{if(oos != null) {oos.close();}  if(ois!= null ) { ois.close() ;}}
使用finally关闭资源的方式是比较安全的,保证关闭操作总是被执行;当关闭资源的时候,确保资源的引用变量是有效的资源而不是 null;为每个物理资源使用单独的 try…catch关闭资源,保证关闭资源的时候,引发的异常不会影响其他资源的关闭。
在Java7中引入的新的自动关闭资源的 try语言:它允许在try关键字之后紧跟一对圆括号,圆括号中可以声明,初始化一个或者多个资源,此处的资源是那些必须在程序结束的时候显式的关闭的资源。,比如数据库连接,网络服务等等。当 try语句结束的时候就会自动关闭这些资源。
需要注意的是为了保证 try语句正常关闭资源,这些资源类需要实现 AutoCloseable或者是Closeable 接口,实现这两个接口就需要实现 close方法。
 
try(
         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“a.bin”));
         ObjectInputStream ois = new ObjectInputStream(new FileInputStream(“a.bin”));
){
oos.writeObject(obj);
oos.flush();
 
Object obj2 =(Object) ois.readObject();
}
这样的话,当超出 try代码块的时候,就会自动关闭打开的资源。需要注意的两点:
          被关闭的资源必须是实现 Closeable或者是AutoCloseable 接口;被关闭的资源必须是在 ()中声明、初始化的。
2.finally 代码块的陷阱
public static void main(String[] args)  {
         // TODO Auto-generated method stub
        FileOutputStream fos = null;
         try {
            fos = new FileOutputStream("Base.java" );
            System. out.println("successful open resource" );
            System. exit(0);
            
        } catch (FileNotFoundException e) {
             // TODO Auto-generated catch block
            e.printStackTrace();
        } finally{
             if(fos !=null ){
                 try {
                    fos.close();
                } catch (IOException e) {
                     // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System. out.println("the program success close resource" );
        }
    }
这样的程序,不会输出 finally的内容。不论 try代码块是正常结束,还是中途非正常的推出, finally代码块都会执行,然而在这个程序中 try代码块根本就没有结束期执行过程,执行 exit的时候,将会停止当前线程还有所有其他当场死亡的线程, finally代码块不能够让停止的线程继续执行
     当System.exit(0) 的时候,JVM退出之前需要完成两项的清理工作:执行系统中注册的所有关闭钩子;如果程序中调用了 System.runFinalizerOnExit(true);那么JVM 就会对还没有结束的对象调用 finalizer;第二种方式是十分危险的,所以一般不会提倡;第一种方式是比较安全的操作。程序中将关闭的操作注册为关闭钩子,在 JVM退出之前,这些关闭钩子就会被调用,保证物理资源被正常关闭。
public static void main(String[] args) throws FileNotFoundException  {
         // TODO Auto-generated method stub
         final FileOutputStream fos;
        fos = new FileOutputStream("a.bin" );
        System. out.println(" 程序打开物理资源 ");
         Runtime.getRuntime().addShutdownHook(new Thread(){
             public void run(){
                 if(fos != null ){
                     try {
                        fos.close();
                    } catch (IOException e) {
                         // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System. out.println(" 程序正常关闭资源 ");
            }
        });
        System. exit(0);
    }
 
Finally 代码块
public static int test(){
         int count = 5;
         try{
             return ++count;
        } finally{
            System. out.println("finally code block");
             return count*2;
        }
        
    }
    public static void main(String[] args ) throws FileNotFoundException  {
         // TODO Auto-generated method stub
         int a = test();
        System. out.println(a);
    }
当 Java程序中执行 try代码块的时候遇到 return代码的时候, return语句会导致该方法立即结束,系统执行完 return语句的时候,并不会立即结束该方法,而是去寻找该异常处理流程中是否包含 finally代码块,如果有的话,则会执行 finally代码块,结束完成之后,在回到原来的 return语句中结束该方法;但是如果在 finally中如果有 return代码的话,就会直接在 finally中结束该方法。
 
Tengfei Yang
于广州中山大学 20131113

Java 进阶6 异常处理的陷阱的更多相关文章

  1. Java进阶5 面向对象的陷阱

    Java进阶5 面向对象的陷阱 20131103 Java是一门纯粹面向对象的编程语言,Java面向对象是基础,而且面向对象的基本语法非常多,非常的细,需要程序员经过长时间的学习才可以掌握.本章重点介 ...

  2. Java进阶02 异常处理

    链接地址:http://www.cnblogs.com/vamei/archive/2013/04/09/3000894.html 作者:Vamei 出处:http://www.cnblogs.com ...

  3. Java进阶02 异常处理(转载)

    异常处理 Java的异常处理机制很大一部分来自C++.它允许程序员跳过暂时无法处理的问题,以继续后续的开发,或者让程序根据异常做出更加聪明的处理. Java使用一些特殊的对象来代表异常状况,这样对象称 ...

  4. java进阶(19)--异常处理机制

    一.基本概念 1.异常的作用: java将异常信息打印至控制台,供程序修改,增加其健壮性. int c=1/0;    //将抛出 java.lang.ArithmeticException 2.异常 ...

  5. Java进阶03 IO基础

    链接地址:http://www.cnblogs.com/vamei/archive/2013/04/11/3000905.html 作者:Vamei 出处:http://www.cnblogs.com ...

  6. Java进阶4表达式中的陷阱

    Java进阶4表达式中的陷阱 20131103 表达式是Java中最基本的组成单元,各种表达式是Java程序员最司空见惯的内容,Java中的表达式并不是十分的复杂,但是也有一些陷阱.例如当程序中使用算 ...

  7. Java进阶篇(四)——Java异常处理

    程序中总是存在着各种问题,为了使在程序执行过程中能正常运行,使用Java提供的异常处理机制捕获可能发生的异常,对异常进行处理并使程序能正常运行.这就是Java的异常处理. 一.可捕获的异常 Java中 ...

  8. Java 进阶 hello world! - 中级程序员之路

    Java 进阶 hello world! - 中级程序员之路 Java是一种跨平台的语言,号称:"一次编写,到处运行",在世界编程语言排行榜中稳居第二名(TIOBE index). ...

  9. Java进阶(五)Java I/O模型从BIO到NIO和Reactor模式

    原创文章,同步发自作者个人博客,http://www.jasongj.com/java/nio_reactor/ Java I/O模型 同步 vs. 异步 同步I/O 每个请求必须逐个地被处理,一个请 ...

随机推荐

  1. pc端弹框

    pc弹框插件:http://aui.github.io/artDialog/doc/index.html#quickref-bubble PC端,手机端,layui很好用,分页啥的:http://ww ...

  2. 受限的用户shell环境

    有些特殊情况下需要实现将系统内普通用户限定在指定目录下,并且只能使用系统管理员设定的命令.lshell就是实现这样功能的一个神器. lshell提供了一个针对每个用户可配置的限制性shell,lshe ...

  3. Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) D. Volatile Kite

    地址:http://codeforces.com/contest/801/problem/D 题目: D. Volatile Kite time limit per test 2 seconds me ...

  4. android studio 版本修改无效解决方案

    我们都知道android的版本声明,是在AndroidManifest.xml文件里面的.例如 <manifest xmlns:android="http://schemas.andr ...

  5. spring cloud 转

    http://blog.csdn.net/forezp/article/details/70148833 服务的注册与发现(Eureka) 服务注册(consul) 服务消费者(rest+ribbon ...

  6. elasticsearch 5.x集群安装

    1. 下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.1.tar.gz 2. 解压 为便于 ...

  7. MyBatis如何返回自增的ID

    <insert id="insertTable" parameterType="com.infohold.city.map.model.CheckTemplateM ...

  8. angularjs 整合bootstrap 时间控件

    一.引入js <link href="${basePath}/static/plugin/bootstrap/css/bootstrap-datetimepicker.min.css& ...

  9. 如何打开windows的远程桌面

    WINDOWS 2003/XP 系列设置方法 右键点击[我的电脑]选择[属性],进入[系统属性]界面,点击[远程]选项卡,勾选[启用这台计算机上的远程桌面]即可. 2003/XP系统默认只允许计算机a ...

  10. 转:web.xml 中的listener、 filter、servlet 加载顺序及其详解

    在项目中总会遇到一些关于加载的优先级问题,刚刚就遇到了一个问题,由于项目中使用了quartz任务调度,quartz在web.xml中是使用listener进行监听的,使得在tomcat启动的时候能马上 ...