============================================
理解
异常就是一种对象,表示阻止程序正常运行的错误或者情况。若异常没有被处理,程序将会非正常退出(很不合理)。
若异常从方法抛出,让调用者捕获该异常并处理该异常是比较合理的,不然就得在方法中判断异常并处理异常(一般用到 if... else..., System.exit(1)...),这并不可取。
异常处理最根本的优势就是将检验错误(由方法完成)从处理错误(由调用方法完成)中分离出来。
可能大家会问:
- 我们的java程序编译时,若程序有异常虚拟机会返回异常,为什么我们/还要去捕获异常?
因为java中有一个异常对象:java.lang.Throwable
image.png
以上名词不过多解释教材上都有。其中 RuntimeException, Error为免检类;其他为必检类。
我们之所以需要捕获、处理异常是因为:Throwable异常类跟所有java类一样,支持被继承和方法重写,以上默认的异常类不能够满足所有的应用场景,实际开发中我们都需要对异常类重现实现(这是我们学习异常类的最终目的)。
注意:一个浮点数除以0是不会产生异常
异常处理的基本模型
- declaring an exception
- throwing an exception
-
catching an exception
image.png
声明异常
在java中,当前执行的语句必须属于某个方法,java解释器调用main方法开始执行一个程序。每个方法都必须声明它可能抛出的必检异常类型。
public void myMethod() throws Exception1, Exception2, ... ExceptionN
注意:如果方法没有在父类中声明异常,那么就不能在子类中对其对其进行继承来声明异常。
抛出异常
检测到错误的程序可以创建一个合适的异常类型的实例并抛出它。
IllegalArgumentException ex = new IllegalArgumentException("Wrong Argument");
throw ex;
//或者
throw new IllegalArgumentException("Wrong Argument");
注意:IllegalArgumentException有两个构造方法,一个无参的一个带可描述这个异常的String参数的。该参数为异常信息(exception message),它可以用getMessage()获得。通常java API中每个异常类都有该特性。
捕获异常
try{
statements; //Statements that may throw exceptions
}
catch(Exception1 exVar1){
handler for exception1;
}
catch(Exception2 exVar2){
handler for exception2;
}
...
catch(ExceptionN exVarN){
handler for exceptionN;
}
如果try语句没有抛出异常,则跳过catch子句。
如果try语句抛出一个异常,java会跳过try的剩下语句。然后查找对应的catch语句(处理器),如果在当前方法中找不到,java会把异常传递给调用这方法的方法。如果调用的方法链中找不到处理器,程序就会终止并在控制台中打印出错误信息。
注意:1、从一个通用父类可以派生出各种异常类。如果一个catch块可以捕获到一个父类的异常对象,那它就能捕获哪个父类的所有子类的异常对象
2、在catch块中异常的指定的顺序非常关键。父类的catch块必须出现在子类catch之前,否则会有编译错误。
3、java强迫程序员处理必检异常
4、catch语句还可以这样写:
catch(Exception1 | Exception2 | ... | ExceptionN){
//Same code for handing these excsptions
}
从异常处理中获取信息
java.lang.Throwable类的实例中有获取有关异常的信息的方法:
- getMessage() : String
返回描述该异常对象的信息。 - toString() : String
返回三个字符的链接:异常类全名 ": " getMessage(方法) - getStackTrace() : StackTraceElement[]
在控制台打印Throwable 对象和它调用堆栈的信息。
public class TestException{
public static void main(String[] args){
try{
System.out.println(sum(new int[] {1, 2, 3, 4, 5}));
}
catch(Exception ex){
ex.printStackTrace();
System.out.println("\n" + ex.getMessage());
System.out.println("\n" + ex.toString());
System.out.println("\n Trace Info Obtained from qetStackTrace");
StackTraceElements[] traceElements = ec.getStackTrace();
for(int i = 0; i < tracdElement.length; i++){
System.out.print("method " + traceElements[i].getMethodName());
System.out.print("(" + traceElements[i].getClassName() + ":");
System.out.println(traceElements[i].getLineNumber() + ")");
}
}
}
private static int sum(int[] list){
int result = 0;
for(int i = 0; i <= list.length; i++){
result += list[i];
}
return result;
}
}
最后的 for 循环有错误,运行结果:

网友评论