异常参数

所有标准异常类都有两个构造器,一个是默认构造器,另一个是接受字符串作为参数,以便能把相关信息放入异常对象的构造器

  1. public class Exception extends Throwable {
  2. static final long serialVersionUID = -3387516993124229948L;
  3. //构造一个新的异常,将null作为其详细信息。原因没有初始化,
  4. 可能随后通过调用initCause进行初始化
  5. public Exception() {
  6. super();
  7. }
  8. //构造一个具有指定详细信息的新异常。原因没有初始化,可能随后通过调用initCause进行初始化。
  9. 参数: Message—详细信息。细节消息被保存,以便稍后由getMessage()方法检索
  10. public Exception(String message) {
  11. super(message);
  12. }

能够抛出任意类型的Throwable类型的异常,因为他是异常类型根类。

抛出异常

当发生错误时,例如,用户输入了非法的字符,我们就可以抛出异常。
如何抛出异常?参考Integer.parseInt()方法,抛出异常分两步:

  1. 创建某个Exception的实例;
  2. 用throw语句抛出。
    1. void process2(String s) {
    2. if (s==null) {
    3. NullPointerException e = new NullPointerException();
    4. throw e;
    5. }
    6. }
    实际上我们会把上面的例子写成一行
    1. void process2(String s) {
    2. if (s==null) {
    3. throw new NullPointerException();
    4. }
    5. }
    如果一个方法捕获了某个异常后,又在catch子句中抛出新的异常,就相当于把抛出的异常类型“转换”了: ```java void process1(String s) { try {
    1. process2();
    } catch (NullPointerException e) {
    1. throw new IllegalArgumentException();
    } }

void process2(String s) { if (s==null) { throw new NullPointerException(); } }

  1. process2()抛出NullPointerException后,被process1()捕获,然后抛出IllegalArgumentException()。
  2. 如果在main()中捕获IllegalArgumentException,看看打印的异常栈:
  3. ```java
  4. public class Main {
  5. public static void main(String[] args) {
  6. try {
  7. process1();
  8. } catch (Exception e) {
  9. e.printStackTrace();
  10. }
  11. }
  12. static void process1() {
  13. try {
  14. process2();
  15. } catch (NullPointerException e) {
  16. throw new IllegalArgumentException();
  17. }
  18. }
  19. static void process2() {
  20. throw new NullPointerException();
  21. }
  22. }
  23. java.lang.IllegalArgumentException
  24. at Main.process1(Main.java:15)
  25. at Main.main(Main.java:5)

这说明新的异常丢失了原始异常信息,我们已经看不到原始异常NullPointerException的信息了。
为了能追踪到完整的异常栈,在构造异常的时候,把原始的Exception实例传进去,新的Exception就可以持有原始Exception信息。对上述代码改进如下:

  1. public class Main {
  2. public static void main(String[] args) {
  3. try {
  4. process1();
  5. } catch (Exception e) {
  6. e.printStackTrace();
  7. }
  8. }
  9. static void process1() {
  10. try {
  11. process2();
  12. } catch (NullPointerException e) {
  13. throw new IllegalArgumentException(e);
  14. }
  15. }
  16. static void process2() {
  17. throw new NullPointerException();
  18. }
  19. }
  1. java.lang.IllegalArgumentException: java.lang.NullPointerException
  2. at Main.process1(Main.java:15)
  3. at Main.main(Main.java:5)
  4. Caused by: java.lang.NullPointerException
  5. at Main.process2(Main.java:20)
  6. at Main.process1(Main.java:13

注意到Caused by: Xxx,说明捕获的IllegalArgumentException并不是造成问题的根源,根源在于NullPointerException,是在Main.process2()方法抛出的。
在代码中获取原始异常可以使用Throwable.getCause()方法。如果返回null,说明已经是“根异常”了