异常参数
所有标准异常类都有两个构造器,一个是默认构造器,另一个是接受字符串作为参数,以便能把相关信息放入异常对象的构造器
public class Exception extends Throwable {
static final long serialVersionUID = -3387516993124229948L;
//构造一个新的异常,将null作为其详细信息。原因没有初始化,
可能随后通过调用initCause进行初始化
public Exception() {
super();
}
//构造一个具有指定详细信息的新异常。原因没有初始化,可能随后通过调用initCause进行初始化。
参数: Message—详细信息。细节消息被保存,以便稍后由getMessage()方法检索
public Exception(String message) {
super(message);
}
能够抛出任意类型的Throwable类型的异常,因为他是异常类型根类。
抛出异常
当发生错误时,例如,用户输入了非法的字符,我们就可以抛出异常。
如何抛出异常?参考Integer.parseInt()方法,抛出异常分两步:
- 创建某个Exception的实例;
- 用throw语句抛出。
实际上我们会把上面的例子写成一行void process2(String s) {
if (s==null) {
NullPointerException e = new NullPointerException();
throw e;
}
}
如果一个方法捕获了某个异常后,又在catch子句中抛出新的异常,就相当于把抛出的异常类型“转换”了: ```java void process1(String s) { try {void process2(String s) {
if (s==null) {
throw new NullPointerException();
}
}
} catch (NullPointerException e) {process2();
} }throw new IllegalArgumentException();
void process2(String s) { if (s==null) { throw new NullPointerException(); } }
当process2()抛出NullPointerException后,被process1()捕获,然后抛出IllegalArgumentException()。
如果在main()中捕获IllegalArgumentException,看看打印的异常栈:
```java
public class Main {
public static void main(String[] args) {
try {
process1();
} catch (Exception e) {
e.printStackTrace();
}
}
static void process1() {
try {
process2();
} catch (NullPointerException e) {
throw new IllegalArgumentException();
}
}
static void process2() {
throw new NullPointerException();
}
}
java.lang.IllegalArgumentException
at Main.process1(Main.java:15)
at Main.main(Main.java:5)
这说明新的异常丢失了原始异常信息,我们已经看不到原始异常NullPointerException的信息了。
为了能追踪到完整的异常栈,在构造异常的时候,把原始的Exception实例传进去,新的Exception就可以持有原始Exception信息。对上述代码改进如下:
public class Main {
public static void main(String[] args) {
try {
process1();
} catch (Exception e) {
e.printStackTrace();
}
}
static void process1() {
try {
process2();
} catch (NullPointerException e) {
throw new IllegalArgumentException(e);
}
}
static void process2() {
throw new NullPointerException();
}
}
java.lang.IllegalArgumentException: java.lang.NullPointerException
at Main.process1(Main.java:15)
at Main.main(Main.java:5)
Caused by: java.lang.NullPointerException
at Main.process2(Main.java:20)
at Main.process1(Main.java:13
注意到Caused by: Xxx,说明捕获的IllegalArgumentException并不是造成问题的根源,根源在于NullPointerException,是在Main.process2()方法抛出的。
在代码中获取原始异常可以使用Throwable.getCause()方法。如果返回null,说明已经是“根异常”了