码迷,mamicode.com
首页 > 其他好文 > 详细

异常中的陷阱

时间:2014-11-15 00:09:48      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   ar   os   使用   sp   

正确关闭资源的方式

①使用finally块来关闭物理资源。

②关闭物理资源时,首先保证引用资源的变量不为null

③每个物理资源时都应该使用单独的try-catch块来关闭资源,保证关闭资源时引发的异常不会影响其他资源的关闭。

finally的陷阱

System.exit(0);

在try中使用了System.exit(0);语句,将停止当前线程和所有其他当场死亡的线程。catch和finally块都不会被执行。因为线程都立即死亡了,怎么会执行下面的东西呢?

那么当出现System.exit(0);语句后,我们怎么来清理物理资源呢?

→将关闭资源的操作注册为关闭钩子。(JVM在退出之前,这些关闭钩子会被调用,从而保证物理资源被正常关闭)。

public class test {
    public  static void main(String[] args) throws Exception {
        final FileOutputStream fos;
        fos=new FileOutputStream("D:\\a.bin");
        System.out.println("程序打开物理资源");
        //为系统注册关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(){
            public void run(){
                //使用关闭钩子来关闭资源
                if(fos!=null){
                    try {
                        fos.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("程序关闭了物理资源");
            }
        });
        //退出程序
        System.exit(0);
    }
}

finally块和try中的return、throw

public class test {
    public  static void main(String[] args) throws Exception {
        int a=test1();
        System.out.println(a);
    }
    public static int test1(){
        int count=5;
        try {
            return count+=5;
        } catch (Exception e) {
            // TODO: handle exception
        }finally{
            System.out.println("finally块被执行");
            return count+=10;
        }
    }
}

打印结果为:

bubuko.com,布布扣

我们来看看反编译后的代码:

public class test {
  public static void main(String[] args) throws Exception {
    int a = test1();
    System.out.println(a);
  }
  
  public static int test1() { int count = 5;
    try {
      count += 5;
    }
    catch (Exception localException) {}finally
    {
      System.out.println("finally块被执行"); }
    count += 10;return count;
  }
}

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

为什么没有放在finally块中呢?因为,从代码块看,count+=2;处于前一个return和后一个return之后,即,当前一个return不起作用的情况下才会执行这个语句。前一个return不起作用的情况只有try中出现了异常,所以count+=2放到了catch块中,而finally块每次都会被执行,放在这里没有任何意义。

bubuko.com,布布扣

因为finally总会被执行,而这里函数已经返回,绝对不会再放后面执行了,所以count是不可达的。出现编译错误。

bubuko.com,布布扣

如果有finally语句,则try中的return 语句会把要返回的值先保存了一份,然后去执行finally语句,finally语句执行完毕之后再返回之前try语句块中保存的那个值,如果try中return的是基本类型的,finally里对变量的改动将不起效果,如果return的是引用类型的,那改动了对象中的值就可以起效果。

bubuko.com,布布扣

try中的return被短路了。

当程序执行try块、catch块时,遇到throw语句时,throw语句会导致该方法立即结束,系统执行throw语句并不会立即抛出异常,而是去寻找该异常处理流程中是否包含finally块。如果没有finally块,程序立即抛出异常;如果有finally块,系统立即开始执行finally块,只有当finally块执行完后,系统才会再次跳回来抛出异常。如果finally块中使用了return语句来结束方法,系统不会跳回去执行try块、catch块去抛出异常。

只能catch try中可能抛出的异常

try中有可能抛出什么异常,后面的catch中才能捕获什么异常,否则会出现编译错误。但是Exception是个例外,即无论try块是什么代码,catch(Exception e)总是正确的。

RuntimeException类及其子类的实例被称为Runtime异常,不是RuntimeException类的及其子类的异常实例被称为Checked异常,如:

bubuko.com,布布扣

只要愿意,程序总可以使用catch(XxxException ex)来捕获运行时异常,它比较灵活,无需显示声明抛出,只要程序需要,即可在任何又需要的地方使用try...catch块来捕获runtime异常。但是catch如果捕获一个Checked异常,那么该catch对象的try必须能抛出该类或其子类的异常。

本文链接:http://www.cnblogs.com/yaoyinglong/p/Java%E5%BC%82%E5%B8%B8%E4%B8%AD%E7%9A%84%E9%99%B7%E9%98%B1.html

异常中的陷阱

标签:style   blog   http   io   color   ar   os   使用   sp   

原文地址:http://www.cnblogs.com/yaoyinglong/p/Java异常中的陷阱.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!