在数据库操作或者I/O读取文件时,通常使用try/catch块进行异常捕获,而将资源回收的代码,比如关闭数据库连接、关闭流等语句写在finally块中,但是发现使用InputStream时,close()函数也是要抛出异常的,感觉这是个比较麻烦的问题,于是翻阅Java核心技术求解,发现其中有个提示是建议采用独立的try/catch和try/finally语句组合,这样就可以捕获finally块中的异常。例如:
InputStream in = ...;try{
   try{
       code may thorw exceptions
   }finally{
       in.close();
   }  
}catch(IOException e){
   do some action
}
于是我按照例子进行了尝试,
public static void throwException(){
File f = null;
FileInputStream fis = null;

try{
try{
f = new File("abc"); 
// 这个文件是不存在的,所以应该抛出FileNotFoundException
fis = new FileInputStream(f);
fis.read();

}finally{
fis.close();

}
}catch(FileNotFoundException e){
System.out.println("file not found");
e.printStackTrace();

}catch(IOException e){
e.printStackTrace();
}

}但是运行之后,却发现抛出的是NullPointerException,是finally中的fis.close()抛出的,没有抛出FileNotFoundException。
后来将finally中的fis.close()移到try语句块中,结果抛出了FileNotFoundException。
发现是finally块中的异常将try中的异常给冲掉了。
在Java核心技术书中,作者建议在finally块中尽量不要使用会抛出异常的资源回收语句,可是有些资源回收语句确实会抛出异常,这个到底该怎么办呢?本人才疏学浅,见得不多,有问题就发到版上,希望版上高手给点解释!!!

解决方案 »

  1.   

    finnlay中
    if(xxx != null){
    try{
    is.close()//关闭资源
    }catch(Exception e){
    //忽略异常
    }
    }以确保finnaly不会有异常发生
      

  2.   

    在finally里如果还有异常,就不能再抛出了,捕获后处理,写到日志里。你的finally写的也不对:public static void throwException(){
        File f = null;
        FileInputStream fis = null;
        
        try{
            
            f = new File("abc"); 
            // 这个文件是不存在的,所以应该抛出FileNotFoundException
            fis = new FileInputStream(f);            
            fis.read();
        }catch(FileNotFoundException e){
            System.out.println("file not found");
            e.printStackTrace();
            
        }catch(IOException e){
            e.printStackTrace();
        } finally{
            try{
                fis.close();
            }catch(Exception e){
                //异常处理,并写入日志
                .......
            }
            
        }           
    }
      

  3.   

    finally中的异常在finally中捕获,不要在外层捕获。
      

  4.   

    发现是finally块中的异常将try中的异常给冲掉了。
    这句话说错了。
    你没有把异常捕获和处理弄明白。
      

  5.   

    finally里面写如果出异常的话,最后处理手段,如果处理手段有问题,可以在finally里面进行try/catch
    ,也可以抛给虚拟机进行处理。
    我是这样觉得
      

  6.   

     public static void throwException(){
            File f = null;
            FileInputStream fis = null;
            
            try{
                try{
                    f = new File("abc"); 
                    // 这个文件是不存在的,所以应该抛出FileNotFoundException
                    fis = new FileInputStream(f);            
                    fis.read();
                    
                }finally{
                    if(fis!=null){//非null,才需要close。若是null。都没占用资源,你还释放什么?                    fis.close();
                    }  
                }
            }catch(FileNotFoundException e){
                System.out.println("file not found");
                e.printStackTrace();
                
            }catch(IOException e){
                e.printStackTrace();
            }
                    
        }
      

  7.   

    使用try-catch,最好先把程序流程弄清楚,要不你的try-catch会写的很乱!!!
      

  8.   


    那就是finally中再进行一次异常捕获呗,之前感觉在finally中进行异常捕获怪怪的
      

  9.   


    2楼的建议和1楼差不多,而且多了日志,谢谢啊我写的这个是引用的java核心技术里面的一种建议,一般情况我也不会这么写,之前以为这是一种比较好的解决办法,结果发现不是
      

  10.   


    public static void main(String[] args) throws IOException {
    InputStream in = new FileInputStream("c:/test.txt");
    try {
    OutputStream out = new FileOutputStream("c:/test1.txt");
    try {
    int len = 0;
    byte[] buffer = new byte[1024];
    while ((len = in.read(buffer)) != -1) {
    out.write(buffer, 0, len);
    }
    out.flush();
    } finally {
    if (out != null) {
    out.close();
    }
    }
    } finally {
    if (in != null) {
    in.close();
    }
    }
    }
      

  11.   

    commons io 包的写法,把异常抛出去或者在最外层处理一下就可以了。
      

  12.   

    谢谢大家的回复,我感觉我把问题搞复杂了
    public static void throwException1(){
        File f = null;
        FileInputStream fis = null;
        
        try{         
            f = new File("abc"); 
            // 这个文件是不存在的,所以应该抛出FileNotFoundException
            fis = new FileInputStream(f);            
            fis.read();
            
        }catch(FileNotFoundException e){
            System.out.println("file not found");
            e.printStackTrace();
            
        }catch(IOException e){
            e.printStackTrace();
        } finally{
            try{ // 在finally对异常进行单独处理
             if(fis!=null){ //非空才关闭
             fis.close();
             }            
            }catch(Exception e){
                //异常处理,并写入日志  
            }
            
        }           
    }
    这样可以万无一失了吧,在finally中进行对fis.close()单独处理异常,并且检查其是否为null,是null则没必要关闭。只检查非空,不用try/catch是不行的