Java异常类层次结构
+-----------+
| Throwable |
+-----------+
/ \
/ \
+-------+ +-----------+
| Error | | Exception |
+-------+ +-----------+
/ | \ / | \
\________/ \______/ \
+------------------+
unchecked checked | RuntimeException |
+------------------+
/ | | \
\_________________/
unchecked
- Error:一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等。如
java.lang.StackOverFlowError
和Java.lang.OutOfMemoryError
。对于这类错误,Java编译器不去检查他们。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和预防,遇到这样的错误,建议让程序终止。 - Exception:表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。
常见的异常:
- OutOfMemoryError:VirtualMachineError的子类,VirtualMachineError是Error的子类;
- StackOverflowError:同上;
- IOException:Exception的子类,属于checked exception。常见的子类有FileNotFoundException等。而IOError则是Error的子类;
- RunTimeException:运行时异常,属于unchecked exception,其常见的子类有NullPointerException等
checked/unchecked Exception分类
- unchecked exception:run-time exception + error;
- checked exception:除了unchecked exception的其他所有异常,即除了RunTimeException及其子类、Error及其子类的所有Throwable的子类。
oracle英文原文见参考资料4。
两者的区别:
- checked exception:必须在代码中处理该Exception,否则会编译不通过。可以通过try-catch或throws让调用者处理;
- unchecked exception:可能是代码逻辑错误引起的,但不处理也能编译通过
throw、throws
- throw用在方法体内,是具体向外抛异常的动作,表示既定事实,如
throw new Exception("error.");
- throws用在函数声明中,表明该函数可能抛出某种类型的异常,需要调用者处理,表示倾向,如
public void test() throws IOException
。
try-catch-finally、try with resources
// before Java 7:
try {
// open resources like File, Database connection, Sockets etc
} catch (FileNotFoundException e) {
// Exception handling like FileNotFoundException, IOException etc
} finally{
// close resources
}
// Java 7 try with resources implementation:
try(// open resources here){
// use resources
} catch (FileNotFoundException e) {
// exception handling
}
// resources are closed as soon as try-catch block is executed.
Java 7之前必须显示的关闭,否则会导致内存泄漏
Java try with resources 的好处:
- 代码的可读性更好,更易于编写代码
- 自动化的资源管理
- 代码的行数被减少
- 不需要使用finally块来关闭资源
- 可在try-with-resources中使用分号来间隔多个资源,会在关闭时通过逆序的方式关闭
任何资源在用于 try-with-resources 时,都需要实现 java.lang.AutoCloseable
,否则Java编译器会抛出编译问题
异常的日志打印
- e:获取的信息包括异常类型和异常详细消息
- e.getMessage:只会获得具体的异常名称. 比如说NullPoint 空指针,就告诉你说是空指针
- e.printStackTrace:会打出详细异常,异常名称,出错位置,便于调试用...一般一个异常至少几十行
在使用slf4j打印异常时,不需要占位符,只需这么打印:logger.error("error = ", e);
,下面这种是错误的:logger.error("error = {}", e);