目录
- 异常介绍
- 异常的作用
- 异常的处理方式
- JVM虚拟机默认处理方式
- 自己处理(捕获异常)
- 抛出异常(交给调用者处理)
- Throwable的成员方法
- 自定义异常
异常介绍
异常就是代表程序出现的问题
学习异常是为了在面对程序出现异常时,能够处理异常
编译时期异常
在编译时,有一些方法会有红色下波浪线,我们需要手动把异常抛出才可以继续编译和运行
这就是编译时异常,特点是需要手动处理,否则代码报错
编译时异常是用来提醒程序员在编写代码时要注意检查本地信息
运行时期异常
在编译时没什么事,但是当运行时代码会报错,这就是运行时异常(如数组访问越界)
运行时异常在编译阶段是不需要做任何处理的,是运行时出现的异常
运行时异常是代码出错而导致出现的问题
异常的作用
作用1
异常是用来查询bug的关键信息
作用2
异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
使用throw关键字抛出异常的对象,即可在调用处看到代码哪里出了问题
异常的处理方式
方式有三种,分别是
JVM虚拟机默认处理方式
- 把异常信息打印在控制台
- 停止执行程序,程序停在了异常出现的位置
自己处理(捕获异常)
- 目的:当代码出现异常后,依旧可以继续往下执行
格式: try{ 可能出现异常的代码; }catch(异常类名 变量名){ 异常处理的代码; } JDK7之后,允许多个异常相同处理方式(中间用 | 隔开) 格式: try{ 可能出现异常的代码; }catch(异常类名1 | 异常类名2 变量名){ 异常处理的代码; }
- 执行完try里的代码若是出现异常,则new一个异常对象E1,把它与catch的参数里的异常类名进行比较,如果一致(也就是可以完成传参)则表示异常被捕获,然后执行catch中的语句,再而执行try/catch体系下的代码
- 那么你试着回答下面四个问题
- 如果try中没遇到问题,怎么执行?
当try中没有遇到问题,那么执行完try中的代码后,就跳过catch往下执行(有点类似if-else)
只有当出现了异常才会执行catch里的代码
- 如果try中可能遇到多个问题,怎么执行?
多个问题,会从上往下运行,它能捕获的则捕获,不能捕获的就交给JVM虚拟机进行默认处理,被捕获的依然执行catch语句,当捕获了一个后就不会执行try中下面的代码了,没有问题或成功捕获最后都会执行捕获体系外下面的代码
那么,多个问题一般要写对应多个catch进行捕获
如果捕获多个异常时,异常有继承关系,那么父类要写在子类下面(父类写在上面代码会报错,因为可能出现多态,使得子类异常被父类异常捕获,那么下面的子类异常就没有机会捕获异常了)
- 如果try中遇到的问题没有被捕获,怎么执行?
相当于try…catch代码白写了,最终还是交给JVM虚拟机进行默认处理
- 如果try中遇到了问题,那么try中下面的代码还会执行吗?
不会了,直接跳转到对应的catch中执行,但如果没有对应的catch与之匹配,那么还是会交给JVM虚拟机进行默认处理
抛出异常(交给调用者处理)
抛出异常的目的就是:告诉调用者出错了
两个关键词
- throws
作用:写在方法定义的参数列表后处,表示声明一个异常,告诉调用者,使用本方法可能会有哪些异常
public void 方法() throws 异常类名1,异常类名2...{ ... }编译时期异常必须要手动写上
时期异常可以不写
- throw
写在方法内,结束方法手动抛出异常对象,交给调用者,方法中下面的代码不再执行
public void 方法名(){ throw new 异常; 下面这部分的代码不再运行,上面抛出就结束了方法 }
Throwable的成员方法
public String getMessage() - 返回此throwable的异常信息
public String toString() - 返回此可抛出的简短描述(异常名字+异常信息)
public void printStackTrace() - 把异常的错误信息输出到控制台(不结束虚拟机,打印的内容包括toString方法的内容+异常的位置)
自定义异常
自定义异常的目的:就是为了让控制台的报错信息更加见名知意
步骤
- 定义异常类
名字要见名知意,要以Exception为后缀表示这是一个异常类
- 写继承关系
运行时异常继承:RuntimeException
编译时异常继承:Exception
-
空参构造
-
带参构造
一个带String类参数表示报错信息的构造即可