总结一些Java异常的处理原则
Java异常处理最佳实践
不要忘记关闭资源
在finally里关闭资源
public void readFile() { FileInputStream fileInputStream = null; File file = new File("./test.txt"); try { fileInputStream = new FileInputStream(file); int length; byte[] bytes = new byte[1024]; while ((length = fileInputStream.read(bytes)) != -1) { System.out.println(new String(bytes, 0, length)); } } catch (FileNotFoundException e) { logger.error("找不到文件", e); } catch (IOException e) { logger.error("读取文件失败", e); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { logger.error("关闭流失败", e); } } }}
用try-with-resource关闭资源
public void readFile2() { File file = new File("./test.txt"); try(FileInputStream fileInputStream = new FileInputStream(file)) { int length; byte[] bytes = new byte[1024]; while ((length = fileInputStream.read(bytes)) != -1) { System.out.println(new String(bytes, 0, length)); } } catch (FileNotFoundException e) { logger.error("找不到文件", e); } catch (IOException e) { logger.error("读取文件失败", e); }}
使用描述性消息抛出异常
指定具体的异常
- 用NumberFormatExcepton而不是Exception,这样能更快的定位问题
- NumberFormatException 是运行时异常
public void numberFormat() { try { String year = "2018"; System.out.println(Integer.parseInt(year)); } catch (NumberFormatException e) { // 捕获NumberFormatExceptoin而不是Exception logger.error("年份格式化失败", e); // 描述一下异常 }}
给异常加注释
// 自定义一个异常class NotFoundGirlFriendException extends Exception { public NotFoundGirlFriendException(String message) { super(message); }}/** * * @param input * @throws NotFoundGirlFriendException input为空抛出异常 */public void doSomething(String input) throws NotFoundGirlFriendException { if (input == null) { throw new NotFoundGirlFriendException("出错了"); }}
优先捕获具体异常
public int getYear(String year) { int retYear = -1; try { retYear = Integer.parseInt(year); } catch (NumberFormatException e) { logger.error("年份格式化失败", e); } catch (IllegalArgumentException e) { logger.error("非法参数", e); } return retYear;}
不要捕获Throwable
- Throwable是所有异常和错误的父类,会把error捕获
- error是那些无法恢复的jvm错误,eg:StackOverflowError和OutOfMemoryError
public void test6() { try { } catch (Throwable e) { }}
不要忽略异常
public void test7() { try { } catch (NumberFormatException e) { logger.error("即便你认为不可能走到这个异常,也要记录一下", e); }}
捕获和抛出只选择一种
- 不要同时记录并抛出异常,会导致相同错误日志输出多次
public void foo() { try { new Long("xyz"); } catch (NumberFormatException e) { logger.error("字符串格式化成Long失败", e); throw e; }}
包装异常不要丢弃原始异常
class MyBusinessException extends Exception { public MyBusinessException(String message) { super(message); } public MyBusinessException(String message, Throwable cause) { super(message, cause); }}public void wrapException(String id) throws MyBusinessException { try { System.out.println(Long.parseLong(id)); } catch(NumberFormatException e) { throw new MyBusinessException("ID格式化失败", e); }}