class InputFile { private BufferedReader in ; // constructor InputFile(String fname) throws Exception{ try { in = new BufferedReader(new FileReader(fname)) ; // other code that might throw exceptions } catch (FileNotFoundException e) { System.out.println("can not open "+ fname) ; // not open ,so not close throw e ; }catch (Exception e) { // all other exceptions must close try { in.close() ; } catch (IOException e2) { System.out.println("in.close() failed") ; } throw e ; }finally{ // do not close here } } String getLine (){ String s ; try { s = in.readLine() ; } catch (IOException e) { System.out.println("readLine failed") ; s = "failed" ; } return s ; } void cleanup (){ try { in.close() ; } catch (IOException e) { System.out.println("in.close failed") ; } } } public class Cleanup{ public static void main(String [] args ){ try { InputFile in = new InputFile("Cleanup.java" ); String s ; int i =1; while((s= in.getLine())!= null){ System.out.println(i +":"+ s); i++; } in.cleanup() ; } catch (Exception e) { System.out.println("catch in main") ; e.printStackTrace() ; } } }
为违例编写代码时,我们经常要解决的一个问题是:“一旦产生违例,会正确地进行清除吗?”大多数时候
都会非常安全,但在构建器中却是一个大问题。构建器将对象置于一个安全的起始状态,但它可能执行一些
操作——如打开一个文件。除非用户完成对象的使用,并调用一个特殊的清除方法,否则那些操作不会得到
正确的清除。若从一个构建器内部“掷”出一个违例,这些清除行为也可能不会正确地发生。所有这些都意
味着在编写构建器时,我们必须特别加以留意。
对 FileReader 来说,除非转移并用它创建一个能够实际
与之“交谈”的 BufferedReader,否则便没什么用处。注意 InputFile 的一个好处就是它同时合并了这两种
行动。
若 FileReader 构建器不成功,就会产生一个 FileNotFoundException(文件未找到违例)。必须单独捕获这
个违例——这属于我们不想关闭文件的一种特殊情况,因为文件尚未成功打开。其他任何捕获从句(catch)
都必须关闭文件,因为文件已在进入那些捕获从句时打开。
用户使用完毕 InputFile 对象后,必须调用 cleanup() 方法,以便释放由 BufferedReader 以及/或者
FileReader 占用的系统资源(如文件句柄)