本文共 4835 字,大约阅读时间需要 16 分钟。
异常
jdk1.7对try--catch--finally的异常处理模式进行了增强,下面我们依次来看增强的方面。
1. 为了防止异常覆盖,给Throwable类增加了addSuppressed方法,可以将一个异常信息追加到另一个异常信息之后:
1 /** 2 * 这是第一种防止前面异常被覆盖的方法,通过在finally块中判断前面是否有异常抛出 3 * 如果有则最终抛出的异常为原来的异常,没有则最终抛出的异常为finally块中的异常。 4 * 此时只能抛出一种异常信息。 5 * @param fileName 6 */ 7 private void readFile(String fileName) { 8 FileInputStream input = null; 9 IOException readException = null;10 try {11 input = new FileInputStream(fileName);12 } catch (IOException ex) {13 readException = ex;14 } finally {15 if (input != null) {16 try {17 input.close();18 } catch (IOException e) {19 // 如果前面没有出现异常,则说明整个异常是此处产生的20 if (readException == null) {21 readException = e;22 }23 }24 }25 26 if (readException != null) {27 throw new RuntimeException(readException);28 }29 }30 }31 32 /**33 * 这是第二种防止异常被覆盖的方法,利用jdk7的新特性。通过在finally块的异常捕获代码中判断前面是否抛出异常,如果抛出异常34 * 则将finally块中抛出的异常追加在前面的异常信息之后。这样同时可以抛出两种异常信息类型。35 * @param fileName36 */37 private void readFile2(String fileName) {38 FileInputStream input = null;39 IOException readException = null;40 try {41 input = new FileInputStream(fileName);42 } catch (FileNotFoundException e) {43 readException = e;44 } finally {45 if (input != null) {46 try {47 input.close();48 } catch (IOException e) {49 // 如果前面抛出的异常不为空,这里将finally块中的异常信息添加到原异常信息后面50 if (readException != null) {51 readException.addSuppressed(e);52 } else {53 readException = e;54 }55 }56 }57 if (readException != null) {58 throw new RuntimeException(readException);59 }60 }61 }
2. catch块增强,可以同时捕获多个异常,来进行统一的处理:
1 /** 2 * 这里测试jdk7的新特性,一个catch语句中可以捕获多种异常,以 | 分割。 3 */ 4 private void catchMore() { 5 // 在jdk1.7新特性这本书中说一个catch块中可以同时捕获属于父子关系的异常(只要子在前父在后,同分开的catch块中的顺序),但实际上在jdk1.8中时不允许的。 6 try { 7 int a = Integer.valueOf("aaa"); 8 throw new IOException(); 9 } 10 /*11 会报NumberFormatException已经被捕获12 catch (NumberFormatException | RuntimeException | IOException e) {13 14 }*/ catch (NumberFormatException | IOException e) {15 16 } catch (RuntimeException e) {17 }18 }
3. throw语句增强,异常在第二次抛出之后,仍然能够准确的知道最原始的异常类型:
1 /** 2 * jdk1.7之后,即使异常被重新抛出,编译器也知道原始异常类型,而不会被再抛出的异常类型所干扰。 3 * 如果在jdk1.6或者之前的版本,第二个catch只能是ExceptionA,因为原始的ExceptionASub2被抹去了。 4 */ 5 private void testRecatch() { 6 try { 7 throw new ExceptionASub2(); 8 } catch (ExceptionA e) { 9 try {10 throw e;11 } catch (ExceptionASub2 e2) { // 如果是catch (ExceptionASub1 e2) 那么会报编译错误,因为编译器知道原始异常是ExceptionASub212 13 }14 }15 }16 17 class ExceptionA extends Exception {}18 class ExceptionASub1 extends ExceptionA {}19 class ExceptionASub2 extends ExceptionA {}
4. try语句增强,try块可以进行资源管理:
1 /** 2 * jdk1.7之后,对try块进行了增强,使其中声明的资源总是可以正确的被释放,而不需要多余的finally块来单独处理。 3 * 这有点像python的 with open("a.txt") as file 语句一样。 4 * 需要注意的是,此时资源必须实现AutoCloseable接口,实际上jdk1.7中通过 5 * public interface Closeable extends AutoCloseable,将Closeable继承于AutoCloseable接口。 6 * 如果我们要自己实现资源的关闭,只需直接实现AutoCloseable接口即可。 7 */ 8 private void tryWithResource() { 9 String fileName = "a.txt";10 try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {11 12 } catch (FileNotFoundException e) {13 14 } catch (IOException e) {15 16 }17 }
变长参数
jdk1.7在变长参数和范型结合使用的时候,增加了一个@SafeVarargs。通过该注解来告诉编译器参数类型的安全性,以此来解决每次调用都出现编译警告的问题。
1 /** 2 * 在jdk1.7之前,需要使用@SuppressWarnings("unchecked")注解来给每一个调用该方法的地方取消警告 3 * 。这是因为变长参数的实际值时通过数组来传递的,而数组中传递的时不可具化的范型对象,自身存在类型安全问题,所以编译器 4 * 会给出警告。这在调用java.utils.Arrays.asList方法和java.util.Collections.addAll方法中也会遇到。 5 * jdk1.7中提供了在该方法声明的地方加上@SafeVarargs注解。来表示该方法在与范型结合使用的时候不会出现类型安全问题。 6 * 此时再调用该方法,编译器不会给出警告信息。 7 * 不过需要注意的是,该方法必须声明为static或者final方法,否则会出现编译错误。 8 */ 9 @SafeVarargs10 public staticT useVarargs(T... args) {11 return args.length > 0 ? args[0] : null;12 }
黎明前最黑暗,成功前最绝望!
转载地址:http://umeoa.baihongyu.com/