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. akka消息传递

    消息传递 消息本身要求是什么?是否必须可以序列化?消息传递根据传递的要求严格程序依次分为三类,1.至多一次到达 至消息最多一次传递到目的端,消息可能会丢失,但不会重复2.至少一次到达 潜在可能存在多次 ...

  2. 【web Api性能提升技巧】(2)从DataReader手工创建Json字符串

    这个思路是从 一篇文章,关于<提升web api的性能>上看到的.自己实践了一番,写下步骤. 传统的DataReader是遵循这样的一个步骤: While(reader.Read()) { ...

  3. maven 介绍(一)

    本文内容主要摘自:http://www.konghao.org/index 内部视频                              http://www.ibm.com/developer ...

  4. Swoole学习(六)Swoole之定时器的创建与清除

    环境:Centos6.4,PHP环境:PHP7,Swoole2.1(在指定的时间后执行函数,需要1.7.7或更高版本) <?php //----------------------------- ...

  5. JavaScript常用算法

    一.排序算法 1.Array.sort(function)(JavaScript原生排序算法)参数:比较函数(可选)若无参数,则按照首字母的ASCII码排序,比较函数的作用为确定排序 function ...

  6. APP开放接口API安全性——Token令牌Sign签名的设计与实现

    在APP开放接口API的设计中,避免不了的就是安全性问题. 一.https协议 对于一些敏感的API接口,需要使用https协议.https是在http超文本传输协议加入SSL层,它在网络间通信是加密 ...

  7. awk十三问-【AWK学习之旅】

    ---===AWK学习之旅===--- 十三个常用命令行处理   [root@monitor awkdir]# cat emp.txt Beth 4.00 0 Dan 3.75 0 Kathy 4.0 ...

  8. 20145324 《Java程序设计》第9周学习总结

    20145324 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作 ...

  9. Windows窗体应用程序常用的几个类的属性、方法以及事件

    System.Diagnostics.Process 属性 public bool EnableRaisingEvents { get; set; }//获取或设置在进程终止时是否应激发 Exited ...

  10. LeetCode——Sort List

    Question Sort a linked list in O(n log n) time using constant space complexity. Solution 分析,时间复杂度要求为 ...