目录
什么是异常,Java提供异常处理机制有什么用?
- 程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常。
- Java把该异常打印输出到控制台,提供给程序员参考,程序员看到异常信息之后,可以对程序进行修改,让程序更加健壮。
Java的异常处理机制
异常在java中以类和对象的形式存在,那么异常的继承结构式怎样的?
我们可以使用UML图来描述一下继承结构。
画UML图又很多工具,例如: Rational Rose ,starUML等
什么是UML?有什么用?
- UML是一种统一建模语言。
- 一种图标式语言。
- UML不是只有Java中使用,只要是面向对象的编程语言,都有UML。
- 一般画UML图的都是软件架构师或者说是系统分析师,这些级别的人员使用的,软件设计人员使用UML。
- 在UML图中可以描述类和类之间的关系,程序执行的流程,对象的状态等。
盖大楼和软件开发一样,一个道理。
盖楼之前,会先由建筑师画图纸,图纸上一个一个符号都是标准符号,这个图纸画完,只要是搞建筑的都能看懂,因为这个图纸上标注的这些符号都是一种标准的语言。
在Java软件开发当中,软件分析师/设计师负责设计类,Java软件开发人员必须要能看懂。
Obeject下有Throwable(可以抛出的)
Throwable下有两个分支:
Error(不可处理的,直接退出JVM)
Exception(可处理的)
Exception下有两个分支:
Exception的直接子类:编译时异常(要求程序员在编写程序阶段必须预先对这些异常继续处理,如果不处理编译器报错,因此得名编译时异常)。
RunTime Exception:运行时异常(在编写程序阶段程序员可以预先处理,也可以不管,都行)
编译时异常和运行时异常,都是发生在运行阶段,编译阶段异常是不会发生的。
- 编译时异常因为什么而得名?
- 因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器就会报错。
- 所有异常都是在运行阶段发生的,因为只有程序运行阶段才可以new对象。
- 因为异常的发生就是new异常对象。
编译时异常和运行时异常的区别:
- 编译时异常一般发生的概率比较高。
- 举个例子:
- 你看到外面下雨了,倾盆大雨的。
- 你出门之气那会预料到:如果不打伞,我可能会生病(生病时一种异常)
- 而且这个异常发生的概率很高,所以我们出门之前要拿一把伞。
- 拿一把伞就是对生病异常发生之前的一种处理方式。
- 对于一些发生概率较高的异常,需要在运行之前对其进行预处理。
- 举个例子:
- 运行时异常一般发生的概率比较低
- 举个例子:
- 小明走在大街上,可能会被天上的飞机轮子砸到。
- 被飞机轮子砸到是一种异常。
- 但是这种异常发生概率较低。
- 在出门之前你没必要提前对这种发生概率较低的异常进行预处理。
- 如果你预处理这些异常,你将活得很累。
- 举个例子:
编译时异常还有其他名字:
受检异常
受控异常
运行时异常还有其他名字:
未受检异常
非受控异常
再次强调:所有异常都是发生在运行阶段的。
java对于异常的两种处理方式:
- 第一种方式:
- 在方法声明的位置上,使用throws关键字,抛给上一级。谁调用我,我就抛给谁,抛给上一级。
- 第二种方式:
- 使用try…catch语句进行异常的捕捉。这件事发生了,谁也不知道,因为我给抓住了。
举个例子:
我是某个公司的一个销售员,因为我的失误,导致公司损失了1000元。
损失1000元这可以看作是一个异常发生了,我有两种处理方式:
第一种方式:我把这件事告诉我的领导(异常上抛)
第二种方式:我自己掏腰包把这个钱补上(异常的捕捉)
张三--->李四--->王五--->CEO
注意:
异常发生之后,如果我选择了上抛,抛给了我的调用者,调用者需要对这个异常继续处理,那么调用者处理这个异常同样有两种处理方式。
注意:
Java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果,终止Java程序的执行。
处理异常的第一种方式:
在方法声明的位置上使用throws关键字抛出,谁调用我这个方法,我就抛给谁。抛给调用者来处理。
这种处理异常的态度:上报
处理异常的第二种方式:
使用try…catch语句对异常进行捕捉。这个异常不会上报,自己把这个事处理了。
注意:
只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行。
另外需要注意,try 语句块中的某一行出现异常,该行后面的代码不会执行。
深入try…catch
- 1、catch你的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。
- 2、catch可以写多个,建议catch的时候,精确的一个一个处理,这样有利于程序的调试。
- 3、catch写多个的时候,从上到下,必须遵守从小到大。
JDK8的新特性:
catch语句里面可以用 | 进行判断
例如: catch( FileNotFoundException | NullPointerException e){}
上报和捕捉怎么选择?
如果希望调用者来处理,选择throws上报。
其他情况使用捕捉的方式。
异常对象有两个非常重要的方法:
- 获取异常简单的描述信息:
- String msg = exception.getMessage();
- 打印异常追踪的堆栈信息:(用这个比较好)
- Exception.printStacktrace();
关于try…catch的finally子句:
- 1、在finally子句中的代码是最后执行的,并且是一定会执行的,即使try语句块中的代码出现了异常。
- 2、finally子句必须和try一起出现,不能单独编写。
- 3、fianlly语句通常使用在哪些情况下呢?
- 通常在finally语句块中完成资源的释放/关闭。
- 因为finally中的代码比较有保障。
- 即使try语句块中的代码出现异常,finally中代码也会正常执行。
try和finally,没有catch可以吗?可以
try不能单独使用
try finally可以联合使用
java中怎么自定义异常呢?
1、编写一个类继承Exception或者RuntimeException。
2、提供两个构造方法,一个无参数的,一个带有String参数的。
重写之后的方法不能比重写之前的方法抛出更多的异常,可以更少。(适用于Exception;Runtime Exception随便)