1.异常的传播
当某个方法抛出异常时:
- 如果当前方法没有捕获,异常就被抛到上层调用方法
- 直到遇到某个try...catch被捕获
- 使用printStackTrace()打印处方法的调用栈
import java.lang.String;
public class Main {
public static void main(String[] args) {
try{
process1();
}catch (Exception e){
e.printStackTrace();//对于调试错误非常有用
}
}
static void process1(){
process2();
}
static void process2() {
Integer.parseInt(null);
}
}
2.抛出异常
- 创建某个Exception的实例
- 用throw语句抛出
import java.lang.String;
public class Main {
public static void main(String[] args) {
try{
process1("");
}catch (Exception e){
e.printStackTrace();
}
}
static void process1(String s){
throw new IllegalArgumentException();
}
}
3.转换异常与持有原有异常
3.1转换异常
如果一个方法捕获了某个异常后,又在catch子句中抛出新的异常,就相当与把抛出的异常类型“转换”了。
import java.lang.String;
public class Main {
public static void main(String[] args) {
process1("");
}
static void process1(String s){
try{
process2(s);
}catch (NullPointerException e){
throw new IllegalArgumentException();//捕获NullPointerException,抛出IllegalArgumentException
}
}
static void process2(String s){
throw new NullPointerException();
}
}
3.2转换的异常持有原有异常
上例中存在的问题:新的异常丢失了原始异常信息,只追踪到process1。如何让新的Exception可以持有原始异常信息?
解决方法:将异常传入即可。
throw new IllegalArgumentException(e);
import java.lang.String;
public class Main {
public static void main(String[] args) {
process1("");
}
static void process1(String s){
try{
process2(s);
}catch (NullPointerException e){
throw new IllegalArgumentException(e);
}
}
static void process2(String s){
throw new NullPointerException();
}
}
4.被屏蔽的异常suppressed exception
在抛出异常前,finally语句会保证执行。
如果finally语句抛出异常,则catch语句不再抛出,没有被抛出的异常被称为“被屏蔽”的异常(suppressed exception)
import java.lang.String;
public class Main {
public static void main(String[] args) {
try{
process1("");
}catch (Exception e){
System.out.println("catched");
throw new RuntimeException(e);//“被屏蔽”的异常(suppressed exception)
}finally {
System.out.println("finally");
//throw new NullPointerException();
}
}
static void process1(String s){
throw new IllegalArgumentException();
}
}
finally中不抛出异常
finally中抛出异常
throw new NullPointerException();去掉注释
因此尽量避免在finally中抛出异常
5.如何保存所有的异常信息
- 使用origin变量保存原始异常
- 如果存在原始异常,用addSuppressed()添加新异常
- 如果存在原始异常,或者新异常,最后在finally抛出
import java.lang.String;
public class Main {
public static void main(String[] args) throws Exception {
Exception origin = null;
try{
process1("");
}catch (Exception e){
origin = e;
System.out.println("catch捕捉到了");
throw new RuntimeException("可能屏蔽的异常"+e);
}finally {
System.out.println("finally");
try{
throw new NullPointerException("finally 抛出的异常");
}catch (Exception e){
if (origin != null ){
origin.addSuppressed(e);
}else{
origin = e;
}
}
if (origin != null){
throw origin;
}
}
}
static void process1(String s){
throw new IllegalArgumentException("process1方法异常了,32");
}
}
5.2获取所有的异常信息
因为一般不在finally中捕获异常,所以可以直接使用for循环将异常信息打印出来。
import java.lang.String;
public class Main {
public static void main(String[] args) throws Exception {
Exception origin = null;
try{
process1("");
}catch (Exception e){
e.printStackTrace();
for(Throwable t:e.getSuppressed()){
t.printStackTrace();
}
}finally {
System.out.println("finally");
}
}
static void process1(String s){
throw new IllegalArgumentException("process1方法异常了,32");
}
}
6.总结:
- printStackTrace()可以打印异常的传播栈,对于调试非常有用
- 捕获异常并再次抛出新的异常时,应该持有原有异常信息。即新抛出的异常应该包含原始异常。
- 如果在finally中抛出异常,应该把新抛出的异常添加到原有异常中
- 用getSuppressed()可以获取所有添加的Suppressed Exception
- 处理Suppressed Exception要求JDK>= 1.7