异常机制的作用
什么是异常,异常的作用?
程序在执行的过程中发生了不正常的情况,这种情况被称之为"异常"。
Java语言是很完善的语言,提供了异常的处理方式:Java把异常信息打印输出到控制台上,供程序员参考。
程序员看到异常后,可以对异常程序进行修改,让程序更加健壮。
异常信息是JVM打印的。
先做一个小小的异常处理,提示除数不能为0
Java语言的完美就在于Java有异常处理机制,它可以在控制台里提示异常信息,帮助程序员处理异常。而不是哑不做声的让程序没有结果也不知道发生了什么。
异常存在的形式
异常以类的形式存在,可以实例化异常对象,可以创建异常对象。
异常分类
Throwable(可抛出)
Throwable是object的子类
Throwable下有两个分支:Error和Exception
Error(不可处理,直接退出JVM)
Exception(可处理)
Exception下有两个分支:Exception的直接子类(编译时异常)和RuntimeException(运行时异常)
编译时异常:要求程序员在编写程序阶段必须预先处理这些异常,如果不处理,编译器会报错。因此叫编译时异常。
也称“受检异常”和“受控异常”。
运行时异常:在编写程序阶段,程序员可以预先处理这运行时异常,也可以不管。
也称“未受检异常”和“非受控异常”。
编译时异常和运行时异常的区别
编译时异常一般发生的概率比较高。
例子:
最近深圳老是下大雨刮台风啥的,我早上出门前都会看下天气预报和观察下天气状况,天气不好的话就带上雨伞和拖鞋。
拿雨伞穿拖鞋就是对“可能会被雨淋湿衣服和侵湿鞋”的异常的预先处理。
预料到可能会发生的异常,我就事先做好准备,做好预处理。防止异常来临时我措手不及。
运行时异常一般发生的概率比较低。
例子:
走在大街上被天上掉下来的馅饼砸到。这种概率极低吧。
如果你整天做好被馅饼砸到的准备,这样不切实际活着也会很累。
不需要预先处理概率极低的异常。
假设Java不对异常进行分类?不分类运行时异常和编译时异常。
因为没有异常的分类,所以需要程序员在写代码时预先处理所有可能会出现的异常。
这样的代码虽然足够应对各种异常,但可读性很差。因为到处都是处理异常的代码。
就像我之前天天背着书包上班一样,书包里有雨伞有雨鞋套,虽然下雨时很应急,但是晴天也背着这些东西就很累啊!
所以现在我就出门时观察下天气,天气不好就带着雨伞,天气好时就啥都不带直接出门,这样挤地铁果然轻松多了。
所有的异常都是发生在运行阶段的。编译也是在运行时在编译的呀。
异常处理的几种方式
异常处理的两种方式throw和try...catch
第一种:throw
在方法声明的位置上,使用throws关键字,抛给上一级。谁调用我,就抛给谁。
第二种:try...catch
使用try...catch语句进行异常的捕捉。这个异常发生了,谁也不知道,因为我给捕捉到了。
生活中异常处理方式的例子:
由于我的失误,给公司造成了1000元的损失,这个“损失1000元”就是公司里的一个异常。
现在我有两种处理异常的方式:
第一种:我把损失这件事告诉我的领导。("异常上抛")
第二种:我自己掏腰包把损失补上。("异常捕捉")
思考:
异常发生后,如果我选择了上抛异常,抛给了我的调用者,由调用者对这个异常继续处理,调用处理这个异常同样也是上述两种方式。
注意:
Java中异常发生后如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,
JVM处理这个异常发生时,只有一个结果,就是终止java程序的执行。
下列程序中,ArithmeticException将异常抛给了它的调用者main,main没有处理这个异常,就将这个异常抛给了JVM。JVM最终终止了程序的执行。
Idea报错编译时异常
下列程序中doSome()方法声明了ClassNotFoundException异常,但是它的调用者main没有处理声明这个异常,所以这个编译时异常出现了,此时Idea编辑器都提示有错,如果不处理,这个main是运行不起来的。
使用Idea的Alt+Enter快捷键可以看到,Idea给出了两种处理异常方式的建议声明和捕捉异常。
第一种方式:上抛异常,类似于推卸责任,继续把异常传递给调用者。
第二种方式:捕捉异常,相等于把异常拦截下来了,真正的把异常给解决了。调用者是不知道发生了什么异常的。
throws上抛异常
处理异常的第一种方式:throws
在方法声明的位置上使用throws关键字抛出,谁调用我这个方法,我就抛给谁,抛给调用者来处理。
以下程序,m3()为什么会抛异常?
根据猜想m3()这里是Idea编辑器提示异常,那就有可能是编译时异常。查看FileInputStream的源码我们可以看到它是间接继承了IOException是编译时异常。所以为什么FileInputStream会报错,是因为在源码里FileInputStream这个方法throws 了FileNotFoundException,此时m3()掉用FileInputStream就也得处理FileNotFoundException这个异常。
当m3() throws FileNotFoundException后,它的调用方m2()又报错了,这和之前m3()报错是同样的道理(m2没有对们throws的异常做处理)。接着m1()、main方法都会报同样的错。
一般不建议在main方法上使用throws,因为这个异常如果真正的发生了,一定会抛给JVM,而JVM只有终止程序。
异常处理机制的作用就是增强程序的健壮性,使程序做到即使程序发生了异常也不影响程序的执行。
所以在main方法中的异常建议使用try...catch来进行异常捕捉。main就不要继续上抛了。