A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 皮卫凯 中级黑马   /  2012-9-16 17:36  /  1515 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 皮卫凯 于 2012-9-16 23:30 编辑

import java.io.*;
class CopyText
{
      public static void main(String[] args) throws IOException
         {
           copy_2();
         }

     public static void copy_2()                            {
               FileWriter fw = null;
               FileReader fr = null;
          try
           {    fw = new FileWriter("SystemDemo_copy.txt");                //这里放一起try,为什么关闭流要分开try
                 fr = new FileReader("SystemDemo.java");
                 char[] buf = new char[1024];
                 int len = 0;
                 while((len=fr.read(buf))!=-1)
                     {
                          fw.write(buf,0,len);     
                     }
             }

        catch (IOException e)
             {
                 throw new RuntimeException("读写失败");
             }

        finally
         {
                 if(fr!=null)
                       try
                         {
                            fr.close();                         //  为什么这两个关闭流要分别分开try,放一起try不也可以吗。
                          }
                      catch (IOException e)
                           {         }
                if(fw!=null)
                       try
                           {
                               fw.close();
                            }
                       catch (IOException e)
                         {      }
     }
}

7 个回复

倒序浏览
如果把close放到第一个try里面,那么如果在close执行前出现了错误,可能就会直接退出,close就无法执行,所以系统资源也就得不到释放,而放在finally里面,因为这个里面的语句是必须执行的所以肯定会执行到close,才能释放系统资源
回复 使用道具 举报
import java.io.*;
class CopyText
{
      public static void main(String[] args) throws IOException
         {
           copy_2();
         }

     public static void copy_2()                            {
               FileWriter fw = null;
               FileReader fr = null;
          try
           {    fw = new FileWriter("SystemDemo_copy.txt");                //这里放一起try,为什么关闭流要分开try-------这里放到一块就可以了!
                 fr = new FileReader("SystemDemo.java");
                 char[] buf = new char[1024];
                 int len = 0;
                 while((len=fr.read(buf))!=-1)
                     {
                          fw.write(buf,0,len);     
                     }
             }

        catch (IOException e)
             {
                 throw new RuntimeException("读写失败");
             }

        finally
         {
                 if(fr!=null)
                       try
                         {
                            fr.close();                         //  为什么这两个关闭流要分别分开try,放一起try不也可以吗-----可以,但是分开写,目的性更强,见后面改写
                          }
                      catch (IOException e)
                           {        
                   throw new exception("读取文件出错");   //添加
}
                if(fw!=null)
                       try
                           {
                               fw.close();
                            }
                       catch (IOException e)
                         {   
              throw new exception("写入文件出错");  //添加这两个抛出异常,会不会更好呢,代码更清晰! IOException 是异常的父类,我们还可以配置确定的异常!
  }
     }
}
回复 使用道具 举报
谢谢答复。
回复 使用道具 举报
谢谢答复。
回复 使用道具 举报
首先为什么关闭流的动作要分开?
因为在我们用到try{}catch(){}处理异常的语句,也就是我们的程序可能导致出现异常的繁发生。
异常一旦发生,执行try{}catch(){}语句,try里面的语句有可能执行不到,就被catch捕获异常,从而处理
加入我们把关闭流的动作放在try语句中,这中情况下流就没有关闭。所以关闭流的动作要放在finally语句中,
因为我们知道finally中存放的是一定能执行到的语句,所以不管有没有发生异常,关闭流总能执行
虽然有一种情况下,就是try或者catch中执行到System.exit(0)时,finally中语句执行不到,但是这种情况下
java虚拟机就退出,所以流会自动随之关闭的

为什么要分开try?
分开try是因为他们满足的条件不一样,要限定FileWriteru和FileReader不为空才能关闭。所以我把楼主finally中语句做了修改
finally
         {
                 if(fr!=null)
                       try
                         {
                            if(fr!=null)
                            fr.close();                         //  为什么这两个关闭流要分别分开try,放一起try不也可以吗。
                          }
                      catch (IOException e)
                           {         }
                if(fw!=null)
                       try
                           {
                              if(fw!=null)
                               fw.close();
                            }
                       catch (IOException e)
                         {      }
     }

这两个判断语句是关闭的前提,一定要加上!
回复 使用道具 举报
吴通 发表于 2012-9-18 07:47
首先为什么关闭流的动作要分开?
因为在我们用到try{}catch(){}处理异常的语句,也就是我们的程序可能导 ...

finally
         {
                 if(fr!=null) //这里已经做了判断
                       try
                         {
                          
  if(fr!=null)   //无需再做判断
                            fr.close();                        
//  为什么这两个关闭流要分别分开try,放一起try不也可以吗。
                          }
                      catch (IOException e)
                           {         }
                if(fw!=null)  //这里已经做了判断
                       try
                           {
                             
if(fw!=null)  //无需再做判断
                               fw.close();
                            }
                       catch (IOException e)
                         {      }
     }

楼上说的,我认为无需再做一次判断了,这样有点多余,只要程序稍微改动一下,就很明了:
finally
         {
                 if(fr!=null) {  //将代码块都使用{}放在if语句下
                       try
                         {
                                   fr.close();                         //  为什么这两个关闭流要分别分开try,放一起try不也可以吗。
                          }
                      catch (IOException e)
                           {         }
                 }
                if(fw!=null) {                    
                     try
                           {
                             
      fw.close();
                            }
                       catch (IOException e)
                         {      }
                }
     }

当然了,这样分开两个try也还是有可能会发生问题,就是在第一个 catch (IOException e){ }中,不能直接抛出RuntimeException异常,这样一但第一个try出现异常,那么第二个try是无法执行到的,也就是无法关闭fw.close();  
这里有两个解决方案
(1)catch (IOException e){ }不抛运行异常RuntimeException,不让程序停止,这样可以执行到fw.close();
  (2)将程序稍作改动:
      finally
         {
                 if(fr!=null) {  //将代码块都使用{}放在if语句下
                       try
                         {
                                   fr.close();                         //  为什么这两个关闭流要分别分开try,放一起try不也可以吗。
                          }
                      catch (IOException e)
                           {         }
                   finally {            
                        if(fw!=null) {                    
                     try
                           {
                             
      fw.close();
                            }
                       catch (IOException e)
                         {      }
                        }
             }
      }


     }

     

     

回复 使用道具 举报
吴通 中级黑马 2012-9-18 15:52:40
8#
我没有看清楚,确实弄错了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马