继承关系

概念
- Exception:程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相关处理
- Checked Exception:源代码显式捕获处理,编译期检查,设计初衷为从异常情况中恢复
- Unchecked Exception(RuntimeException):可以编码避免的逻辑错误,不会在编译期强制要求
- Error:在正常情况下,不太可能出现,绝大部分的Error都会导致程序处于不可恢复的状态
ClassNotFoundException
1 | Thrown when an application tries to load in a class through its string name using: |
找不到.class
文件
NoClassDefFoundError
1 | Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class |
能找到.class
文件,但ClassLoader
尝试加载类的定义时却找不到该类的定义
最佳实践
反例1
1 | try { |
- 不要捕获通用异常
Exception
,应该捕获特定异常InterruptedException
- 不要捕获
Throwable
或Error
,否则很难保证能够正常处理OutOfMemoryError
- 不要捕获
- 不要生吞异常,出现故障后难以诊断
反例2
1 | try { |
- 在复杂的生产环境中,
stderr
不是一个合适的输出选项,很难判断输出到哪里去了 - 最佳实践:使用产品日志,输出到日志系统
Throw early, catch late
Throw early
1 | public static void main(String[] args) throws FileNotFoundException { |
1 | public static void main(String[] args) throws FileNotFoundException { |
Catch late
捕获异常后,如果实在不知道如何处理,可以保留原有异常的cause信息,直接再抛出或者构建新的异常抛出
自定义异常
- 是否定义成
Checked Exception
,Checked Exception
的设计初衷是为了从异常情况中恢复- 我们作为异常的设计者,是有充足的信息对异常进行分类的,是否满足
Checked Exception
的设计初衷
- 我们作为异常的设计者,是有充足的信息对异常进行分类的,是否满足
- 在保证诊断信息足够的同时,也需要避免包含敏感信息(例如用户信息),可能会导致潜在的安全问题
性能开销
try-catch
会产生额外的性能开销,往往会影响JVM对代码进行优化- 尽量仅捕获有必要的代码块,尽量不要使用大
try-catch
块 - 不要使用
try-catch
来控制代码流程,比常规的条件语句(if/else,switch)要低效
- 尽量仅捕获有必要的代码块,尽量不要使用大
- 每实例化一个
Exception
,都需要对当时的栈进行快照,这是一个比较重的操作- 当服务吞吐量下降时,可以考虑检查发生最频繁的
Exception
- 当服务吞吐量下降时,可以考虑检查发生最频繁的