Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类。
Throwable又派生出Error类和Exception类。
程序员通常无能为力,一旦发生,想办法让程序优雅的结束 。
错误不能被程序员通过代码处理,Error很少出现。
比如:用户输入错误,设备错误,物理限制
可以被Java异常处理机制使用,是异常处理的核心。
是程序员自己程序导致的问题,可以捕获、可以处理。
(2) Classification of exceptions
运行时异常(RuntimeException):由程序员在代码里处理不当造成
是程序源代码中引入的故障所造成的 ,如果在代码中提前进行验证,这些故障就可以避免
其他异常:由外部原因造成,是程序员无法完全控制的外在问题所导致的 ,
即使在代码中提前加以验证(文件是否存在),也无法完全避免失效发生。
(3) Checked and unchecked exceptions
a.Unchecked exceptions( Errors and Runtime Exceptions)
不需要在编译的时候用try…catch等机制处理
可以不处理,编译没问题,但执行时出现就导致程序失败
Unchecked异常也可以使用throws声明或try/catch进行捕获,
但大多数时候是不需要的,也不应该这么做
b.Checked exceptions
必须捕获并指定错误处理器handler,否则编译无法通过
Java's exception handling consists of three operations:
– Declaring exceptions (throws) 声明“本方法可能会发生XX异常”
– Throwing an exception (throw) 抛出XX异常
– Catching an exception (try, catch, finally) 捕获并处理XX异常
例如:
c.Use checked or unchecked exceptions in your code?
①当要决定是采用checked exception还是unchecked exception的时候,
问一个问题:“如果这种异常一旦抛出,client会做怎样的补救?”
如果客户端可以通过其他的方法恢复异常,那么采用checked exception;
错误可预料,但无法预防,但可以有手段从中恢复,此时使用checked exception;
如果客户端对出现的这种异常无能为力,那么采用unchecked exception;
异常出现的时候,要做一些试图恢复它的动作而不要仅仅的打印它的信息。
②尽量使用unchecked exception来处理编程错误
如果client端对某种异常无能为力,
可以把它转变 为一个unchecked exception,程序被挂起并返回客户端异常信息
③不要创建没有意义的异常,
client应该从checked exception中获取更有价值的信息(案发现场具体是什么样子)
利用异常返回的信息来明确操作失败的原因。
如果client仅仅想看到异常信息,可以简单抛出一个unchecked exception:
④总结:
Checked exception应该让客户端从中得到丰富的信息。
要想让代码更加易读,倾向于用unchecked exception来处理程序中的错误
(4)Declaring Checked Exceptions by throws
a.“异常”也是方法和 client端之间spec的一部分,在post-condition中刻画
比如:public FileInputStream(String name) throws FileNotFoundException
如果方法不止抛出一个异常,必须把所有异常写出来
比如:public Image loadImage(String s) throws FileNotFoundException, EOFException
b. 你的方法应该throws什么异常?
①你所调用的其他函数抛出了一个checked exception——从其他函数传来的异常
②当前方法检测到错误并使用throws抛出了一个checked exception——你自己造出的异常
此时需要告知你的client需要处理这些异常
如果没有handler来处理被抛出的checked exception,程序就终止执行
程序员必须在方法的spec中明确写清本方法会抛出的所有checked exception, 以便于调用该方法的client加以处理
c.不要抛出 Error 和 unchecked exceptions
比如:void drawImage(int i) throws ArrayIndexOutOfBoundsException // bad style!
d.关于子类和父类
①如果子类型中override了父类型中的函数,
那么子类型中方法抛出的异常不能比父类型抛出的异常类型更宽泛 。
②子类型方法可以抛出更具体的异常,也可以不抛出任何异常 。
③如果父类型的方法未抛出异常,那么子类型的方法也不能抛出异常。
例如
(5) How to Throw an Exception
a.throw new EOFException();
或者
EOFException e = new EOFException();
throw e;
b.利用Exception的构造函数,将发生错误的现场信息充分的传递给client。
比如
String gripe = "Content-length: " + len + ", Received: " + n;
throw new EOFException(gripe);
c.步骤
①找到一个能表达错误的Exception类/ 或者构造一个新的Exception类
②构造Exception类的实例,将错误信息写入
③抛出它
一旦抛出异常,方法不会再将控制权返回给调用它的client,因此也无需考虑返回错误代码
(6) Creating Exception Classes
如果JDK提供的exception类无法充分描述你的程序发生的错误,可以创建自己的异常类
public class InsufficientFundsException extends Exception {}
(7) Catching Exceptions
异常发生后,如果找不到处理器,就终止执行程序,在控制台打印出stack trace
To catch an exception, set up a try/catch block
也可以不在本方法内处理, 而是传递给调用方,由client处理(“推卸责任”)
尽量在自己这里处理,实在不行就往上传——要承担责任!
但有些时候自己不知道如何处理,那么提醒上家,由client自己处理
(8) finally Clause
当异常抛出时,方法中正常执行的代码被终止
如果异常发生前曾申请过某些资源,那么异常发生后这些资源要被恰当的清理
Java has a better solution: the finally clause.
不管程序是否碰到异常,finally都会被执行
若找不到异常处理程序,整个系统完全退出