String、StringBuffer、StringBuilder的区别?
Java异常
- What:异常类型回答了什么被抛出
- Where:异常堆栈跟踪回答了在哪抛出
- Why:异常信息回答了为什么被抛出
Error和Excpetion的区别
- Error,程序无法处理的系统错误,编译器不做检查。一般是与JVM相关的问题:系统崩溃、虚拟机错误、内存空间不足、方法调用栈溢出等。
- Exception,程序可以处理的异常,捕获后可能恢复。
- 前者是程序无法处理的错误,后者是可以处理的异常。
上图可知,Error和Exception都是继承至Throwable类,Exception类派生的子类为:RuntimeException(不可避免,程序应当自行避免,如nullPointer异常)和非RuntimeException(可预知的,从编译器校验的异常,如IO异常、sql异常等)。因为Error和Exception都是继承至Throwable类,因此都是可以被抛出的。
- Error属于JVM需要担负的责任
- RuntimeException是程序应该担负的责任
- Checked Exception可检查异常是Java编译器应该担负的责任,虽然可以被抛出粗化异常,但是一般还是需要捕获处理。
常见Error和Exception
RuntimeException
- NullPointerException-空指针引用异常(调用了空对象方法的属性、方法)。
- ClassCastException-类型强制转换异常
- IllegalArgumentException-传递非法参数异常(给方法传入了错误类型的参数、错误参数个数)。
- IndexOutOfBoundsException-下标越界异常
- NumberFormatException-数字格式化异常
非RuntimeException
- ClassNotFoundException-找不到指定class的异常
- IOException-IO操作异常
Error
- NotClassDefFoundError-找不到class定义的异常
- 类依赖的class或者jar不存在
- 类存在不同的域中
- 大小写问题,javac编译是忽视大小写的,而编译出来的class文件区分大小写
- StackOverflowError-深递归导致栈被耗尽
- OutOfMemoryError-内存溢出异常
Java的异常处理机制
- 抛出异常:创建异常对象交由运行时系统(系统对象中包含了,异常类型、异常时程序运行状态)包含了处理
- 捕获异常:运行时系统会寻找合适的异常处理器处理异常发生时依次停留在调用栈中的方法集合,当异常处理器所能处理的异常与抛出的异常相符时,即为合适的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直到找到含有异常处理器的方法并执行。如果没找到,则程序终止运行。
- finally会在catch中的return语句之前执行,按顺序去匹配异常处理块,且只会被其中一个匹配到。捕获到的异常不能简单打印到控制台,最好持久化到日志中。
Java异常的处理原则
具体明确:抛出的异常应能通过异常类名和message准确说明异常的类型和产生异常的原因。
提早抛出:应尽可能早地发现并抛出异常,便于精确定位问题。
延迟捕获:异常的捕获和处理应尽可能延迟,让掌握更多信息的作用域来处理异常。
高效主流的异常处理框架
在用户看来,应用系统发生的所有异常都是应用系统内部的异常。
- 设计一套通用的继承至RuntimeException异常来统一处理。
- 其余异常都统一转译为上述异常AppException。
- 在cache之后,抛出上述异常的子类,并提供足以定位的信息。
- 由前端接收AppException做统一处理。
- 参考Spring框架的异常处理机制
try-catch的性能
- try-catch块影响JVM的优化(指令重排序)
- 异常对象实例需要保存栈快照等信息,开销较大