在Java中,所有的异常对象都是派生与java.lang.Throwable这个类。但在下一阶段,Throwable会分解成两个部分:Error与Exception。
基本上,遇到Error类的问题,都是由于系统的运行错误或者资源耗尽,而不是由于程序的设计错误。在这种情况下,我们除了将错误报告给用户,并尽力使程序安全退出之外,别无他法(有个疑问,书里是这样说的(也有可能是我记忆错乱),但如果是我们一开是在设计程序的时候分配的内存太大而引起内存溢出的错误,那么我们是否可以通过修改代码而避免发生这种错误)。我们设计的程序中,不应该抛出这种异常(或者说是错误,虽然我也不知道如何抛出这种异常,囧)。
我们在设计程序时,需要注意的是Exception。Exception可以分支为两个部分:运行时异常与受检异常(checked exception)。其中的受检异常有时候并非是我们设计的程序出了问题,而是由于外部的因素而引起的,比如文件读写异常、数据库异常等等。当程序发生了运行时异常时,往往都是程序设计的不够规范而导致的。比如说,抛出ArrayIndexOutOfBoundsException异常时,往往是我们没有去检测数组下标是否越界;当抛出NullPointerException时,大多数情况下都是我们在使用变量前没有检查其是否为空。而我们也应该尽量去避免发生这种情况。
异常处理的语法
我们在编写程序时,需要处理异常,对于受检异常,一般有两种处理方式:在方法首部声明中使用throws抛出异常;或者使用try...catch...finally语句去捕获并处理它。
try...catch...finally
如果程序在try语句块中抛出了catch子句中说明的异常,那么程序将跳过try语句块中余下的部分,转而去执行catch子句中处理异常的代码;若是在try语句块中没有抛出异常,那么程序将跳过catch子句.
e.g:
try{//
code that might throwexception//
}catch(IOException e) {//
show exception message//
}finally{//
}//
比如说像上面这个例子,在try语句块中,首先执行1部分的代码,
1)如果没有抛出异常,那么程序依次会执行1,2, 5, 6部分的代码,因为此时并没有异常去给catch捕获到,程序此时会跳过catch部分的代码;
2)如果程序抛出了一个IOException的异常,那么这个异常会被catch捕获到,此时程序转去执行catch的代码,最后执行finally的代码;
3)如果程序抛出了一个异常,但并没有被catch语句捕获(在这里的例子中抛出不属于IOException的异常),那么此异常依然会被抛出,但此时程序会跳过余下的try语句块的代码和catch的代码,然后执行finally的代码。此时,1, 5部分的代码会被执行。
有时候,try语句块里面的代码,执行时可能并不只是抛出一种异常,而是多种异常,当无论抛出哪种异常时,处理的动作都相同,那么可在catch后面的圆括号里,不同的异常之间用 | 分隔开来,如果不同的异常有不同的处理方式,那么我们需要多个catch语句:
1)如果需要捕获的异常之间并无父子类的关系,那么声明顺序不作要求;
2)如果需要捕获的异常之间是属于父子类的关系时,需要按顺序声明:子类异常必须要在父类异常的前面,否则会报错。
throws + 异常类型
throws: 用于方法首部,声明此方法可能会抛出某种异常(甩锅)
throw:用于方法内部,手动抛出异常
如果在方法首部使用了throws,调用者要么去解决抛出的异常,要么也使用throws进行声明。如果一个方法,在内部可能会抛出受检异常(checked exception)时,必须在首部使用throws声明,如果是可能抛出RuntimeException时,方法可以不用throws进行声明。如果一个方法可能会抛出多个受检异常,那么必须要进行多异常声明,异常之间用逗号分隔开,或者直接声明抛出它们的父类异常。
throw是用在方法内部,程序设计者需要考虑出现问题的情况,如传递数据的时候,如果用户传递了不合法的参数,那么就应告诉调用者,传递合法的数据进来.这时需要用抛出异常的方式来告诉调用者。使用格式为:
throw new xxException();
需要注意的是,throw这个关键字必须在方法的内部,并且抛出的异常对象必须是Exception或Exception的子类对象,而且一旦抛出异常对象,我们就必须对这个对象进行处理(当然如果是RuntimeException或其子类,我们可以交由JVM去处理)。
比较
1.如果父类中的方法并没有使用throws进行声明,那么子类中重写该方法时也不能用throws进行声明,如果重写的方法中可能会抛出异常,那么可以使用try...catch...finally的方式对异常进行处理。
2.执行的方法 a 中, 先后又调用了另外的几个方法, 而这几个方法又是递进关系执行的, 我们建议这几个方法使用throws的方式进行处理,而执行的方法a可以考虑用try...catch...finally的方式进行处理。