在构造方法中存在异常的惯用处理法
thinking in java 中的一个例子,这个惯用法保证了在构造方法中抛出异常的代码能够正常处理:
1 package test ; 2 3 import java.io.BufferedInputStream; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.IOException; 7 8 class InputFile { 9 private BufferedInputStream in = null ; 10 private File file = null ; 11 public InputFile(String filepath ) throws IOException { 12 file = new File(filepath) ; 13 in = new BufferedInputStream(new FileInputStream(file)); 14 15 } 16 public String getFileContent() throws IOException { 17 byte[] content = new byte[(int)file.length()] ; 18 in.read(content) ; 19 return new String(content) ; 20 } 21 public void dispose() throws IOException{ 22 in.close(); 23 System.out.println("dispose successful ! "); 24 } 25 } 26 public class Cleanup{ 27 public static void main(String[] args) { 28 try{ 29 InputFile input = new InputFile("这里写文件路径") ; 30 try{ 31 String content = input.getFileContent() ; 32 }catch(Exception e ){ 33 e.printStackTrace(); 34 } 35 finally{ 36 input.dispose(); 37 } 38 }catch(Exception e){ 39 e.printStackTrace(); 40 } 41 } 42 }
在main方法中可以确保文件正常打开才执行dispose方法,也就是关闭文件的方法。
还有将InputFile类构造方法中的异常抛出是有意义的,书上原话为:
“异常被重新抛出,对于构造器而言这么做是很合适的,因为你总不希望去误导调用方,让他以为这个对象已经创建完毕,可以使用了”
上面的编码格式可以扩展广泛一点,基本规则是:“在创建需要清理的对象之后,立即进入一个try-fianlly语句块”:
分为两种情况,1 : 构造方法可能会失败也就是可能会抛出异常 2 : 构造方法不会失败
当构造方法不会抛出异常的情况:
1 class TestClean1 { 2 public TestClean1() { 3 // 比如打开了很多资源 4 } 5 /** 6 * 执行该类的清理工作 7 */ 8 public void clean(){} 9 } 10 class TestClean2 { 11 public TestClean2() { 12 } 13 /** 14 * 执行该类的清理工作 15 */ 16 public void clean(){} 17 } 18 public class TestCleanup { 19 public static void main(String[] args) { 20 21 TestClean1 clean1 = new TestClean1() ; 22 TestClean2 clean2 = new TestClean2() ; 23 try{ 24 // 在这里执行clean1和2的代码 25 }finally{ 26 clean1.clean(); 27 clean2.clean(); 28 } 29 } 30 }
当构造器会出现错误的时候:
1 class TestClean1 { 2 public TestClean1() throws Exception { 3 throw new Exception() ; 4 } 5 /** 6 * 执行该类的清理工作 7 */ 8 public void clean(){} 9 } 10 class TestClean2 { 11 public TestClean2() throws Exception { 12 throw new Exception() ; 13 } 14 /** 15 * 执行该类的清理工作 16 */ 17 public void clean(){} 18 } 19 public class TestCleanup { 20 public static void main(String[] args) { 21 try{ 22 TestClean1 clean1 = new TestClean1() ; 23 try{ 24 TestClean2 clean2 = new TestClean2() ; 25 try{ 26 // 执行clean1和clean2的代码 27 }finally{ 28 clean2.clean(); 29 } 30 }catch(Exception e ){ 31 System.out.println("clean2构造失败"); 32 e.printStackTrace(); 33 }finally{ 34 clean1.clean(); 35 } 36 }catch(Exception e ){ 37 System.out.println("clean1构造失败"); 38 e.printStackTrace(); 39 } 40 } 41 }
当构造方法抛出异常表示没有正常打开资源,也就不需要清理。上面代码保证了两个对象都能够正确的清理。