1、java标准异常概述
Throwable表示任何可以作为异常被抛出的类,有两个子类Error和Exception。从这两个类的源代码中可以看出,这两个类并没有添加新的方法,Throwable提供了所以方法的实现。Error表示编译时和系统错误。Exception是可以被抛出的异常类。RuntimeException继承自Exception(如NullPointerException),表示运行时异常,JVM会自动抛出.
2、自定义异常类
自定义异常类方法: 通过继承Throwable或Exception。异常类的所有实现都是基类Throwable实现的,所以构造自定义异常类完全可以参考Exception和Error类。我们只要添加上自定义异常类的构造方法就可以了
<span style="font-size:16px;">package demo.others;
/**
* 自定义异常类方法
* 1、通过继承Throwable
* 2、通过继承Exception
*
* @author Touch
*/
public class MyExceptionDemo extends Exception {
private static final long serialVersionUID = 1L;
public MyExceptionDemo() {
super();
}
public MyExceptionDemo(String message) {
super(message);
}
public MyExceptionDemo(String message, Throwable cause) {
super(message, cause);
}
public MyExceptionDemo(Throwable cause) {
super(cause);
}
}
</span>
</div>
3、异常栈及异常处理方式
可以通过try、catch来捕获异常。捕获到的异常。下面的示例演示了几种常用异常处理方式
<span style="font-size:16px;">package demo.others;
import mine.util.exception.MyException;
public class ExceptionDemo1 {
public void f() throws MyException {
throw new MyException("自定义异常");
}
public void g() throws MyException {
f();
}
public void h() throws MyException {
try {
g();
} catch (MyException e) {
//1、通过获取栈轨迹中的元素数组来显示异常抛出的轨迹
for (StackTraceElement ste : e.getStackTrace())
System.out.println(ste.getMethodName());
//2、直接将异常栈信息输出至标准错误流或标准输出流
e.printStackTrace();//输出到标准错误流
e.printStackTrace(System.err);
e.printStackTrace(System.out);
//3、将异常信息输出到文件中
//e.printStackTrace(new PrintStream("file/exception.txt"));
//4、重新抛出异常,如果直接抛出那么栈路径是完整的,如果用fillInStackTrace()
//那么将会从这个方法(当前是h()方法)作为异常发生的原点。
//throw e;
throw (MyException)e.fillInStackTrace();
}
}
public static void main(String[] args) {
try {
new ExceptionDemo1().h();
} catch (MyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
</span>
</div>
运行结果:
f g h main mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo1.f(ExceptionDemo1.Java:7) at demo.others.ExceptionDemo1.g(ExceptionDemo1.Java:11) at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16) at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35) mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7) at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11) at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16) at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35) mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7) at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11) at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16) at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35) mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:30) at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)</div>
分析上面的程序,首先main函数被调用,然后是调用h函数,再g函数、f函数,f函数抛出异常,并在h函数捕获,这时将依次从栈顶到栈底输出异常栈路径。
4、异常链
有时候我们会捕获一个异常后在抛出另一个异常,如下代码所示:
<span style="font-size:16px;">package demo.others;
import java.io.IOException;
import mine.util.exception.MyException;
public class ExceptionDemo2 {
public void f() throws MyException {
throw new MyException("自定义异常");
}
public void g() throws Exception {
try {
f();
} catch (MyException e) {
e.printStackTrace();
throw new Exception("重新抛出的异常1");
}
}
public void h() throws IOException {
try {
g();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IOException("重新抛出异常2");
}
}
public static void main(String[] args) {
try {
new ExceptionDemo2().h();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
</span>
</div>
运行结果:
mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9) at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32) java.lang.Exception: 重新抛出的异常1 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32) java.io.IOException: 重新抛出异常2 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)</div>
从结果中我们可以看出,异常栈变小了。也就是说丢失了最原始的异常信息。怎样保存最原始的异常信息呢?Throwable类中有个Throwable cause属性,表示原始异常。通过接收cause参数的构造器可以把原始异常传递给新异常,或者通过initCause()方法。如下示例:
<span style="font-size:16px;">package demo.others;
import java.io.IOException;
import mine.util.exception.MyException;
public class ExceptionDemo2 {
public void f() throws MyException {
throw new MyException("自定义异常");
}
public void g() throws Exception {
try {
f();
} catch (MyException e) {
e.printStackTrace();
throw new Exception("重新抛出的异常1",e);
}
}
public void h() throws IOException {
try {
g();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
IOException io=new IOException("重新抛出异常2");
io.initCause(e);
throw io;
}
}
public static void main(String[] args) {
try {
new ExceptionDemo2().h();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
</span>
</div>
结果:
mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9) at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34) java.lang.Exception: 重新抛出的异常1 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17) at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23) at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34) Caused by: mine.util.exception.MyException: 自定义异常 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9) at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14) ... 2 more java.io.IOException: 重新抛出异常2 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27) at demo.

