Java基础知识总结(10)——异常

异常:本质上是程序的错误

错误在我们编写程序过程中经常发生,包括编译期间和运行期间的错误

比如说括号没有配对   或者少了分好,   关键字编写错误等等

通常编译器帮我们一起修订


但是运行期间错误编译器就无能为力了





这些都是运行期间的错误

在程序运行过程中,意外发生的情况,背离我们程序本身的意图的表现都可以理解为异常

可以理解为一种事件

Java通过Throwable已经相关子类来对各种异常进行描述

Throwable是Java异常重要的根类

他有两个子类 Exception和Error


Error是程序无法处理的错误,表示运行应用程序中较严重的问题

大多数问题与代码编写者执行的操作没有关系的,而表示运行时JVM出现的一系列的问题

这些错误是不可能查的 

他们在应用程序的控制和处理能力之外,而且大多数是在程序运行时不允许出现的状况


对于设计合理的应用程序来说,即使缺失发生了错误,本质上也不应该试图去处理它所引起的异常状况

对于Error及其子类产生的异常我们是不需要关心的,不过我们也及其不希望在程序运行出现这种错误


Exception是程序本身可以处理的异常。异常处理通常只针对这种类型的异常处理。

非检查异常:编译器不要求强制处理的异常,包含RuntimeException以及相关子类,比如说上面的最上面的几种异常

 Java编译器在编译阶段不会检查这些异常的,不过程序员在写代码的时候可以捕获处理这些异常,也可以选择放仍不管

编译器不会针对这些操作产生任何信息的


与之对应的是检查异常:编译器要求必须处理的异常

在Java当中除了RuntimeException和他的子类都是CheckException

比如说IO异常和SQL异常


在Java应用程序中异常处理分为两大机制:1 抛出异常  2 捕获异常

不过异常一定要先被抛出然后才能被捕获


抛出异常:当一个方法当中出现错误引发异常的时候,方法会创建异常对象并且交付给运行时系统处理


捕获到了异常就会进入捕获异常环节

在这个阶段,运行系统就会逐步去找合适的处理器

如果找到了与抛出异常匹配的处理器,就会执行相关的处理逻辑

如果始终没有找到运行系统将会终止,这时就意味着Java程序停止了


对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同


Java规定:对于可查异常必须捕捉,或者声明抛出

    允许忽略不可查的RuntimeException(含子类)和Error(含子类)


抛出异常和捕获异常Java通过5个关键字实现

try   catch  finally throw  throws


try、catch、finally这三个一组作为捕获异常

throws声明

throw抛出异常


try-catch-finally


try块:用于捕获异常

catch块:用于处理try捕获的异常

finally块:无论是否发生异常代码总能执行


一个try块后面可以接0个或者多个catch块,如果没有catch块,则必须跟一个finally块


就是try必须要和catch和finally组合使用,不允许单独存在

cacth和finally没有try的加入也是无法单独行动的


当我try了之后抛出的异常被catch捕获 ,catch执行结束后依然执行后面相关代码

e.printStackTrace();打印出错误的堆栈信息

错误描述+错误类型+错误出现的位置

 但是这个出错信息相对比较随机~~~


从最后一行看,调用了Scanner的nextInt方法...接下去


我们为了保证一定执行可以加上finally


表示无论怎样都一定执行的代码


我们希望针对不同异常有不同处理方式

Java运行多重catch结构

比如说Exception的子类ArithmeticException算数异常

(一个trycatch不能出现同类型异常)


就像我们不能保证所写代码块不能出错一样

我们也不能保证所写的分类异常涵盖了所有异常信息

所以为了安全起见我们建议在多重catch块添加一个异常的父类Exception,用它来追踪在子类无法捕获的异常


我们要求Exception一定要放在最后一个

不能放在前面,如果放在前面相当于后面两个都没用了


什么情况能够强制终止finally执行?

在一个异常添加一句

System.exit(1);


这样执行到这里程序就结束了


System类下的

public static void exit(int status);终止程序运行

参数描述中止状态

只要不是数字0就是异常终止状态

通常情况下在异常处理中写个非0就可以了终止,finally也无法


return:



我们发现无论程序是否正常执行,输出的都是finally的

通过断点跟踪,我们发现直接调到-100000

因为finally强制执行的作用

所以finally里不推荐用return


throw和throws


通过throws什么将要抛出何种类型的异常,通过throw将产生的异常抛出

如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法什么处用throws子句来什么抛出异常

throws语句用在方法定义时声明该方法要抛出的异常类型


当方法抛出异常列表中的异常时,方法将不对这些类型及其子类类型的异常做处理,而抛向调用该方法的方法,由他去处理


我们修改原来的代码自己不处理,让调用者处理



Surround With自动检查调用方法产生的异常类型


这样就可以了


出现别的异常就没法搞定了

方案1 多种异常逗号分开


分别处理


第二种:

我预测这段代码可能产生异常,并且可能产生不同类型的异常

而我又不耐烦一个一个去写

我可以直接写父类throws Exception



这样是可以的,但是我声明的是exception异常你在调用必须处理这个异常

自写上面两个会出错的,但是只写exception不出错


Exception异常如果抛出必须处理,但是算数什么的可以不处理

以为一类是检查异常一类是非检查异常


如果我希望非检查异常能够有一定提示,我们就可以用文档注释


当鼠标悬停在方法上就会有提示


可以通过throw来抛出异常对象

例如:throw new IOException();

throw抛出的只能够是可抛出类Throwable或者其子类的实力对象

例如:throw new String("出错了");是错误的



有上述2个方案

1 自己抛出异常自己处理

2 谁调用方法谁处理异常


我们throw异常不仅可以规避出现的风险,还可以完成一些程序的逻辑


注意:上述案例输入不是数字就没有处理

Exception这个类他有一个带字符串参数的构造方法

可以通过字符串参数描述他的异常信息


或者throws

发现抛出exception或者throwable(我们选择exception)

然后在调用处处理


我们可以选择继续往上抛,或者try catch


如果抛出throwable 在 catch处也要是throwable

可以抛出它的父类的

不过不能是子类,因为范围比他小,不能描述他的相关错误信息的

另外不太建议抛出非检查异常


我们可以使用Java内置的异常类可以描述在编程时出现的大部分异常

也可以通过自定义异常描述特定业务产生的异常类型

所谓自定义异常,就是定义一个类,去继承Throwable类或者他的子类




这样就可以了,个人表示自己曾经PHP项目开发过程中用的很多


异常链:

有时候我们捕获一个异常后抛出另一个异常


这样的话只会保留最后的异常信息,把前面的信息丢掉了

我们需要保留异常的话,就得用保留异常机制



我们可以看到这些异常全出来了,我们把异常的原因,发生过程全部记录了保留下来了


异常链:我们捕获一个异常后抛出另一个异常

将异常发生的原因一个传一个串起来,即把底层的异常信息传给上层,这样逐层抛出


我们可以通过throw和throws抛出和声明异常


可以通过throws声明将要抛出何种形势的异常,通过throw将产生的异常抛出

如果一个方法可能会出现异常,但没有能力处理这种能力,可以在方法声明处用throws语句来声明抛出异常


当子类重写父类抛出异常的方法时,声明的异常必须是父类方法所声明异常的同类和子类


这时候会出错

这样才可以






阅读更多
个人分类: Java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭