随着项目开发的规模越来越大,越往底层,可能抛出的异常类型也会越来越多。

  如果上层想要处理这些异常,就需要挨个的写很 try-catch语句块来捕捉异常,这样是很麻烦的。

  如果我们对底层抛出的异常捕获后,抛出一个新的统的异常,的确可以避免这个问题。但是直接抛出一个新的异常,又可能会造成最原始的异常信息丢失,不利于排查问题。

  这里只是为了演示,实际工作都是Spring统一异常处理,没有try-catch,这里演示的是异常链传递异常的问题。

例子如下:

public class Test {
	public static void main(String[] args) {
		try {
			checkEx3();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void checkEx3() throws Exception {
		try {
			checkEx2();
		} catch (Exception e) {
			Exception e1 = new Exception("第3个异常");
			throw e1;
		}
	}
	
	public static void checkEx2() throws Exception {
		try {
			checkEx1();
		} catch (Exception e) {
			Exception e2 = new Exception("第2个异常");
			throw e2;
		}
	}
	
	public static void checkEx1() throws Exception {
		throw new Exception("第1个异常");
	}
}

打印结果如下

Java异常链的常见问题_异常丢失

  你会发现,最初出现的是异常1,然后异常2,这些信息都不见了,只出现了最后一次异常3,这对于排错非常不利。

解决方案如下:

public class Test {
	public static void main(String[] args) {
		try {
			checkEx3();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void checkEx3() throws Exception {
		try {
			checkEx2();
		} catch (Exception e) {
			// 异常链写法1
			Exception e1 = new Exception("第3个异常");
			e1.initCause(e); // 异常链信息的传递
			throw e1;
			// 异常链写法2
//			throw new Exception("第3个异常", e);
		}
	}
	
	public static void checkEx2() throws Exception {
		try {
			checkEx1();
		} catch (Exception e) {
			// 异常链写法1
			Exception e2 = new Exception("第2个异常");
			e2.initCause(e); // 异常链信息的传递
			throw e2;
			// 异常链写法2
//			throw new Exception("第2个异常", e);
		}
	}
	
	public static void checkEx1() throws Exception {
		throw new Exception("第1个异常");
	}

}

Java异常链的常见问题_异常丢失_02


  这样就能看到最初的第1个异常和第2个异常了。采用异常链,在保有底层异常信息的基础上,将多层次异常以链路方式进行封装,对后续追查定位BUG是非常有利的

  推荐异常链写法1。因为initCause方法相对更加灵活,可以在异常对象构造完成单独进行异常信息赋值。

  异常链写法2是利用异常的根类Throw中提的带参构造方法 Throwable (String message, Throwable cause)实现异常链信息的传递。

  对于异常信息传递的作用而言,写法1和2无区别。


欢迎一键三连~



有问题请留言,大家一起探讨学习



----------------------Talk is cheap, show me the code-----------------------