有一点很重要,即你要时刻询问子句"如果异常发生了,所有东西能被正确清理码?",尽管大多数情况下时非常安全的,但涉及到构造器时,问题出现了,构造器会把对象设置成安全的初始状态,但还会又别的动作,比如打开一个文件,这样的动作只有在对象使用完毕并且用户调用了特殊的清理方法之后才能得以清理,如果在构造器内抛出了异常,这些行为也许就不能正常工作了,这意味着在编写构造器时要格外细心.
用finally也许可以解决问起,但问题并非如此简单,因为finally会每次都执行清理操作,如果构造器在执行过程中半途而废,也许该对象的某部分还没有创建成功就要被清理,这又会抛出新的异常(.close()也会抛出异常)
1.构造器抛出异常要格外注意清理方法是否有必要调用,如果方法恰当,直接向上层抛出的确能简化编程
package exceptions; //: exceptions/InputFile.java // Paying attention to exceptions in constructors. import java.io.*; public class InputFile { private BufferedReader in; public InputFile(String fname) throws Exception { try { in = new BufferedReader(new FileReader(fname)); // Other code that might throw exceptions } catch(FileNotFoundException e) { System.out.println("Could not open " + fname); // Wasn\'t open, so don\'t close it //如果没有打开文件就不需要关闭 throw e; } catch(Exception e) { // All other exceptions must close it 如果时其它异常则必须关闭文件 try { //in.close()也可能抛出异常,所有要放到try块里面 in.close(); } catch(IOException e2) { System.out.println("in.close() unsuccessful"); } throw e; // Rethrow } finally { //由于finally总会被执行,如果在这里关闭文件则文件刚打开还没开始使用就关闭了 // Don\'t close it here!!! } } public String getLine() { String s; try { s = in.readLine(); } catch(IOException e) { //这这异常已被捕获,因此getLine不会抛出任何异常 throw new RuntimeException("readLine() failed");//重新抛出新的异常到上层环境,有时会简化编程 } return s; } public void dispose() { try { in.close(); System.out.println("dispose() successful"); } catch(IOException e2) { throw new RuntimeException("in.close() failed"); } } } ///:~