码迷,mamicode.com
首页 > 编程语言 > 详细

java异常

时间:2019-11-16 10:43:06      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:完全   将不   执行   程序   生命周期   内存   第一个   null   ror   

异常允许

  1. 允许我们强制程序停止运行,并告诉我们出现了什么问题
  2. 强制程序处理问题,并返回到稳定状态()

异常可能离异常被抛出的地方很远,也可能会跨越方法调用栈的许多层次。

通常::异常对象中仅有的信息就是异常类型,除此之外无其它内容

异常处理程序:try{}catch{}

try{}后可以有多个catch{},每个catch子句相当于一个 接收且仅接收一个特殊类型的参数的方法。可在处理程序的内部使用标识符 (id1,id2 等)。

当try中捕捉到对应异常后,放入对应的catch子句中进行处理,一旦catch子句结束,则处理程序的查找过程结束。只有相匹配的catch子句才能得到执行。

 

在try中,许多不同的方法调用会产生类型相同的异常,你仅需提供一个针对此类型的异常处理程序 即可。

终止与异常:

  1. 终止模型:一旦异常被抛出,就表明错误无法挽回,也不能回来继续执行
  2. 恢复模型:异常处理程序修正错误,然后重新尝试调用出现问题的方法,并认为第二次能成功。   但恢复模型容易导致 耦合,恢复性的处理程序需要了解异常抛出的地点,势必要包含依赖于抛出位置的非通用性代码,增加了代码维护难度。

 

自己定义异常类,必须从已有的异常类继承,最好选择意思相近的异常类继承。

异常与记录,使用java.util.logging 工具将输出记录到日志中。

各级别按降序排列如下:

  • SEVERE(最高值)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST(最低值)

此外,还有一个级别OFF,可用来关闭日志记录,使用级别ALL启用所有消息的日志记录。

logger默认的级别是INFO,比INFO更低的日志将不显示。

Logger的默认级别定义是在jre安装目录的lib下面。

 

栈轨迹:

得到异常的调用栈。

技术图片

 

重新抛出异常:

重新抛出异常(1.将try获取的异常在catch中重新抛出,但不使用fillInStackTrace()方法  ;  2.将try获取的异常在catch中重新抛出,使用fillInStackTrace()方法  ; 3.捕获到异常后,在catch中抛出另一个异常)

  1. 异常对象的所有信息得以保持: 将刚得到的异常重新抛出,重抛异常把异常抛给上一级环境中的异常处理程序,同一个try 块的后续 catch 子句将被忽略。此外,异常对象的所有信息都得以保持,所以高一级异常处理程序可以从这个异常对象中得到所有信息。
  2. 更新异常的信息(相当于新的异常):在重抛异常时调用fillInStackTrace()方法,将返回一个Throwable对象,通过将当前调用栈信息填入原来的异常对象而建立(相当于新对象取代了旧对象),因此原先异常发生点的信息将丢失。
  3. 捕获异常后抛出另一种异常:这样做的效果类似于 使用了 fillInStackTrace(),有关原异常发生点的信息会丢失,剩下的都是新的抛出点的信息。

异常链:

捕获一个异常后 抛出另一个异常,并希望把原始异常的信息保存下来,这样被称为 异常链。

程序员必须自己编写代码保存原始异常信息,现在所有Throwable的子类在构造器中都可以接受一个cause 对象作为参数 。这个cause 就用来表示原始异常,这样通过把原始异常传递给新的异常,使得 即使在当前位置创建并抛出了新的异常,也可通过这个异常链接起来。(Throwable的子类中,仅Error、Exception、RuntimeException 提供了带cause参数的构造器,如果要把其他类型的异常链接起来,应该使用initCause()方法而不是构造器 )

技术图片

java标准异常:

Throwable对象可分为两种类型(从Throwable继承而得到的类型)1.Error(一般表示编译时和系统错误),2.Exception(可以被抛出的基本类型)。。。。输入输出从java.io.IOException中继承而来

运行时异常都是从RuntimeException中继承而来,如果RuntimeException没有被捕获而直达main(),那么程序退出前将调用异常的printStackTrace()方法。

只能在代码中忽略RuntimeException(及其子类)类型的异常,其他类型异常的处理都是由编译器强制实施的,RuntimeException代表编译时期错误:

  1. 无法预料的错误。如:从你控制之外传进来的null引用
  2. 在一个地方发生的异常,常常会在另一个地方导致错误

使用finally进行清理:(java有垃圾回收)

对于无垃圾回收和析构函数自动调用机制的语言来说,finally非常重要,finally可保证 无论try块里发生了什么,内存总能得到释放。

java中使用:当需要把内存之外的资源恢复到初始状态(如,文件等内存之外的),这时,将需要finally子句

由于存在异常被抛出后并没有被异常处理程序捕获的情况,因此,可以使用finally,使其一定被执行,释放资源等。

在return中使用finally

技术图片

 

构造器

在编写构造器时需要格外小心,它会把对象设置成安全的初始状态,但还会有别的动作,如 打开一个文件,这样的动作只有在对象使用完毕且用户调用了特殊的处理方法后才能得以清理。如果构造器内抛异常了,这些清理行为也许就不能工作了。

对上面一句话的理解:构造器在调用一个方法时,可能还未使用完毕,若此时构造器出异常,并程序员在finally中清理了资源,那么,这个方法无法正常工作,无法得到正确的使用。

例子:我们希望一个文件在Fileclass的整个生命周期中都是打开状态,因此在构造器中,我们不应该在finally中关闭这个文件,因为每次执行完构造器都会执行一遍关闭。

 

异常匹配:

抛出异常的时候,异常处理系统会按照代码的书写顺序找出“最近”的处理程序。找到匹配的程序之后,就被认为异常已得到处理,就不会再寻找了。 在寻找处理程序时,不要求完全匹配,派生类的对象也可以匹配其基类的处理程序。     如果基类异常处理类  放在对应  异常处理类的 前面,那么异常处理类将永远得不到执行,这时编译器将向你报告错误。

 

异常处理重要原则:只有在你知道如何处理的情况下才捕获异常。   

异常处理的重要目标:把错误处理的代码与错误发生的地点相分离。这样 主干程序代码 不会和错误处理代码逻辑  相混合,代码更易于维护。

 

java的“被检查的异常”  ::程序小时,”被检查的异常“的好处很明显,当程序日益增大时,就会携带一些问题(原来可以控制的问题,现在无法处理了),这些问题可能是由于过多的“类型检查”所引起的。

异常使用指南:

  1. 在恰当的级别处理问题。(当你知道如何处理的时候 才应该捕获异常)
  2. 解决异常并重新调用产生异常的方法
  3. 绕过异常发生的地方
  4. 用别的数据进行计算,代替方法预计会返回的值
  5. 把当前环境下能做的事尽量做完,然后把相同的异常重抛到更高层
  6. 把当前环境下能做的事尽量做完,然后把不同的异常抛到更高层
  7. 终止程序
  8. 让类库和程序更安全

 

总结:

异常处理优点:你可以在某处集中精力处理你要解决的问题,而在另一处处理你编写的这段代码中产生的错误

 

try{}中如果两个地方都有异常,则,仅会捕捉第一个

在catch中重抛异常,throw (Exception) e.fillInStackTrace();    仅保存重抛位置的信息,其余不保存。

 

 

java异常

标签:完全   将不   执行   程序   生命周期   内存   第一个   null   ror   

原文地址:https://www.cnblogs.com/acg88688/p/11870571.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!