通过异常处理错误
java的基本理念是“结构不佳的代码不能运行”
java异常处理的目的在于通过使用少于目前数量的代码来简化大型,可靠的程序的生成,并通过这种方式可以使你更加自信:你的应用没有未处理的错误。
异常的相关知识学起来并非艰涩难懂,并且它属于那种可以使你的项目收益明显,立竿见影的特性之一。
一、概念
对于构造大型健壮可维护的程序而言,不去检查错误的错误处理模式情形已经成为了主要障碍。解决方法是,用强制规定的形式来消除处理过程中随心所欲的因素。
使用异常能够降低错误处理代码的复杂度。使用异常,就不必在方法调用处进行检查,因为异常处理机制能够捕捉这个错误。异常机制,使代码阅读编写和调试工作井井有条。
二、基本异常
异常情形是指阻止当前方法或作用域继续执行的问题。
当跑出异常后,有几件事会随之发生。首先,将使用new在堆上创建异常对象,然后,当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理截止接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理程序,它的任务是将程序从错误状态中恢复,以使程序能要么换一种方式运行,要么继续运行下去。
异常最重要的方面之一就是如果发生问题,他们将不允许程序沿着其正常的路径继续走下去。异常允许我们强制程序停止运行,并告诉我们出了什么问题,或者强制程序处理问题,并返回到稳定状态。
Throwable对象是异常类型的根类。对于不同类型的错与,要抛出相应的异常。错误信息可以保存在异常对象内部或者用异常类的名称来暗示。
三、捕获异常
要明白异常是怎么捕获的,必须首先理解监控区域的概念。它是一端可能产生异常的代码,并且后面隔着处理这些异常的代码。
try块:在方法块里尝试各种(可能产生异常的)方法调用,然后只需在一个地方就可以捕获所有异常。
异常处理程序:以关键字catch表示。异常被抛出时,异常处理机制将负责搜索参数与异常类型相匹配的第一个处理程序。进入catch字句执行,此时认为异常得到了处理,一旦catch字句结束,处理程序的查找过程结束。
在try块的内部,许多不同的方法调用可能会产生类型相同的异常,而你只需要提供一个针对此类型的异常处理程序。
终止与恢复:异常处理理论上有两种基本模型。
java支持终止模型,一旦异常被抛出,就表明错误已无法挽回,也不能回来继续执行。另一种称为恢复模型,意思是异常处理程序的工作是修正错误,然后重新尝试调用出问题的方法,并认为第二次能成功。
四、创建自定义异常
不必拘泥于java中已有的异常类型。java提供的异常体系不可能遇见所有的希望加以报告的错误。
要自己定义异常类,必须从已有的异常类继承,最后选择意思相近的异常类继承。建立新的异常类型最简单的方法就是让编译器为你产生默认构造器。
五、异常说明
java鼓励人们把方法可能会抛出的异常告知使用此方法的客户端程序员,它使得调用者能确切知道写什么样的代码可以捕获所有潜在的异常。
异常说明使用了附加的关键字Throws,后面接一个所有潜在异常类型的列表。
代码必须与异常说明保持一致。编译器会提醒要么处理这个异常,要么就在异常说明中表明此方法将产生异常
六、捕获所有的异常
通过捕获异常类型的基类Exception可以捕获所有类型的异常。这将捕获所有的异常,最好放到列表末尾,防止它抢在其他处理程序前把异常捕获。
Exception是基类,不会包含太多具体的信心,可以调用它从基类Throwable继承的方法。
重抛异常会把异常抛给上一级环境中的异常处理程序,同一个try块的后续catch字句将被忽略。
在捕获一个异常后抛出另一个异常,并且希望把原始异常信息保留下来,被称为异常链。
七、JAVA标准异常
Throwable这个Java类被用来表示任何可以作为异常被抛出的类,分为两种类型:Error表示编译时和系统错误,Exception是可以被抛出的基本类型。
异常的基本的概念是用名称代表发生的问题,并且异常的名称应该可以望文知意。
八、使用finally进行清理
对于一些代码,可能希望无论try块中的异常是否抛出,他们都能得执行。这通常适用于内存回收之外的情况。在异常处理程序后面加上finally,无论异常是否被抛出,finally子句总能被执行。
在return中执行finally,可以保证重要的清理工作仍旧会执行。
异常丢失:异常作为程序出错的标志,有可能被忽略,使用finally可以做出处理。
九、异常的限制
当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。异常限制对构造器不起作用,派生类构造器不能捕获基类构造器抛出的异常。
一个在基类方法的异常说明中的异常,不一定会出现在派生类方法的异常说明里。
十,构造器
构造器会把对象设置成安全的初始状态,也会在对象使用完毕并且用户调用了特殊的清理方法之后才能得以清理。如果在构造器内抛出异常,这些清理的行为也许就不能正常工作。
十一、异常匹配
抛出异常的时候,异常处理系统会按照代码的书写顺序找出最近的处理程序。找到匹配的处理程序之后,它就认为异常将得到处理,然后就不再继续查找。
查找的时候并不要求抛出的异常通处理程序所声明的异常完全匹配。派生类的对象也可以匹配其基类的处理程序。
十二、其他可选方式
异常处理系统就像一个活门,使你能放弃程序的正常执行序列。异常代表了当前方法不能继续执行的情形。
开发异常处理的初衷是为了方便程序员处理错误。另一个重要原则是:只有你知道如何处理的情况下才捕获异常。
异常处理的一个重要目标是把错误处理的代码同错误发生的地点相分离。
减少编译时施加的约束能显著提高程序员的编程效率。事实上,发射和泛型就是用来补偿静态类型检查所带来的过多显著。
十三,异常使用指南
1,在恰当的级别处理问题(在知道如何处理的情况下捕获异常)。
2,在解决问题并且重新调用产生异常的方法。
3,进行少许修补,然后绕过异常发生的地方继续执行。
4,用别的数据进行计算,以代替方法预计会返回的值。
5,把当前运行环境下能做的事情尽量做完,然后把 相同/不同 的异常跑到更高层。
6,终止程序。
7,进行简化(如果你的异常模式使问题变得太复杂,那用起来会非常痛苦也很烦人)。
8,让类库和程序更安全(这既是在为调试做短期投资,也是在为程序的健壮性做长期投资)。
十四、总结
报告功能是异常的精髓所在。java坚定地强调所有的错误都以异常形式报告的这一事实,正是它远远超过诸如C++这类语言的长处之一。