总结一些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);
}
}