异常:本质上是程序的错误
错误在我们编写程序过程中经常发生,包括编译期间和运行期间的错误
比如说括号没有配对 或者少了分好, 关键字编写错误等等
通常编译器帮我们一起修订
但是运行期间错误编译器就无能为力了
这些都是运行期间的错误
在程序运行过程中,意外发生的情况,背离我们程序本身的意图的表现都可以理解为异常
可以理解为一种事件
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语句来声明抛出异常
当子类重写父类抛出异常的方法时,声明的异常必须是父类方法所声明异常的同类和子类
这时候会出错
这样才可以