前言
JAVA提供强大的异常处理机制,在Java中,所有的异常都会被封装到一个类中,程序出错时会将异常抛出。
一、如何知道程序错误
代码中的错误是客观存在的,没有十全十美的代码,代码多到一定程序,我们就需要不断维护、检查代码的错误,确保健壮性。
在Java中,我们有以下两种方式告诉程序代码发生错误:
- LBYL: Look Before You Leap. 在操作之前就做充分的检查
- EAFP: It’s Easier to Ask Forgiveness than Permission. “事后获取原谅比事前获取许可更容易”. 也就是先操作, 遇到问题再处理.
简单来说就是第一种没有使用异常,第二采用了异常的方法
代码风格如下:
LBYL: Look Before You Leap. 在操作之前就做充分的检查:
boolean ret = false;
ret = 登陆游戏();
if (!ret) {
处理登陆游戏错误;
return; }
ret = 开始匹配();
if (!ret) {
处理匹配错误;
return; }
ret = 游戏确认();
if (!ret) {
处理游戏确认错误;
return; }ret = 选择英雄();
if (!ret) {
处理选择英雄错误;
return; }
ret = 载入游戏画面();
if (!ret) {
处理载入游戏错误;
return; }
......
It’s Easier to Ask Forgiveness than Permission. “事后获取原谅比事前获取许可更容易”. 也就是先操作, 遇到问题再处理:
try {
登陆游戏();
开始匹配();
游戏确认();
选择英雄();
载入游戏画面();
...
} catch (登陆游戏异常) {
处理登陆游戏异常;
} catch (开始匹配异常) {
处理开始匹配异常;
} catch (游戏确认异常) {
处理游戏确认异常;
} catch (选择英雄异常) {
处理选择英雄异常;
} catch (载入游戏画面异常) {
处理载入游戏画面异常; }
.....
对比两种不同风格的代码, 我们可以发现:
使用第一种方式, 正常流程和错误处理流程代码混在一起, 代码整体显的比较混乱.
而第二种方式正常流程和错误流程是分离开的, 更容易理解代码
二、常见的异常
所谓异常指的就是程序在 运行时出现错误时通知调用者的一种机制
异常的种类有很多, 不同种类的异常具有不同的含义, 也有不同的处理方式,下面介绍几种常见异常:
1.算术异常
public static void main(String[] args) {
System.out.println(10/0);
}
2.数组越界异常
public static void main(String[] args) {
int []arr=new int[4];
System.out.println(arr[10]);
}
3.空指针异常
public static void main(String[] args) {
String str=null;
System.out.println(str.length());
}
二、异常的基本用法
1.如何捕获异常
异常处理是由try、catch与finally等3个关键字组成的程序块。 其异常的基本语法:
try{
要检查的程序语句;
...
}
catch(异常类 对象名称){
异常发生时的处理语句;
}
[
catch(异常类 对象名称){
异常发生时的处理语句;
}
catch(异常类 对象名称){
异常发生时的处理语句;
}
...
]
[finally{
一定会运行到的程序代码;
}
]
异常的处理流程如下:
- 首先,我们把所有可能发生异常的语句都放到一个try之后由{}所形成的区块,这个区块称为“try区块”。程序通过try{}区块准备捕捉异常。try程序块若有异常发生,程序的运行便重点,并抛出“异常类所产生的对象”。
- 抛出的对象如果属于catch()括号内欲捕获的异常类,catch则会捕捉此异常,然后进入catch的块里继续运行。
- 无论try程序块是否捕捉到异常,或者捕捉到的异常是否与catch()括号内的异常相同,最终一定会运行finally块里的程序代码。
【注意】 finally块时可以省略的,如果省略了finally块,那么在catch()块运行结束后,程序将跳到try-catch块之后继续执行。
流程图如下: 下面看一个例子: 不进行异常处理:
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println(arr[10]);
}
使用异常处理就能正常编译:
public static void main(String[] args) {
int[] arr = {1, 2, 3};
try{
System.out.println(arr[10]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("我在这里捕捉到一个异常");
}
System.out.println("hello!!!");
}
如果我想要知道详细的异常信息的话,则需要使用异常对象的printStackTrace()方法:
【异常处理机制小结】 当异常发生时,通常用两种方法处理:
- 一种时交由Java默认的异常处理机制做处理。但这种处理方式,Java通常只能输出异常信息,接着便终止程序的运行
- 一种时用自行编写的try-catch-finally块来捕捉异常,这样的好处是可以灵活操控程序的流程,做出最适当的处理。
2.异常类的处理流程
习惯上将Error类与Exception类统称为异常类,但二者本质上是不同点。 Error类通常指的是Java虚拟机出错,用户无法在程序里处理这种错误。 Exception类包含了一般性的异常,这些异常在捕捉到之后便可做妥善的处理,以确保程序继续运行。
下面是异常处理的流程:
- 如果程序发生异常,那么会自动地由JVM根据异常的类型,实例化一个指定异常类的对象,如果这个时候程序之中没有任何的异常操作,则这个异常类的实例化对象将交给JVM进行处理——进行异常信息的输出,而后中断程序执行
- 如果程序之中存在异常处理,则会由try语句捕获产生的异常类对象;然后将该对象与try之后的catch进行匹配,如果匹配成功,则使用指定的catch进行处理,如果没有匹配成功,则向后面的catch继续匹配,如果没有任何的catch匹配成功,则这个时候将交给JVM执行默认处理。
- 不管是否有异常都会执行finally程序,如果此时没有异常,执行完finally,则会继续执行程序之中的其他代码,如果此时有异常没有能够处理(没有一个catch可以满足),那么也会执行finally,但执行完finally之后,将默认交给JVM进行异常信息的输出,并且程序中断。
3.throws关键字
我们可以使用 throws 关键字, 把可能抛出的异常显式的标注在方法定义的位置. 从而提醒调用者要注意捕获这些异常。 格式如下:
访问权限 返回值类型 方法名称(参数列表)throws 异常类{
}
上面格式包括两个部分:一个普通方法的定义,与方法定义模式无区别。方法后面紧跟”throws异常类“,它位于方法体{ }之前,用来检测当前方法是否有异常,若有,则将该异常提交给直接使用这个方法的方法。
private static void setZero(int[] arr,int index)throws ArrayIndexOutOfBoundsException{
arr[index]=0;
}
public static void main(String[] args) {
int []arr=new int[5];
try{
setZero(arr,10);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组超出绑定方位!");
System.out.println("异常:"+e);
}
System.out.println("main()方法结束!");
}
4.throw关键字
上面的所有异常类对象全部都是由JVM自动实例化的,但优势我们也想能进行异常类对象的实例化操作,手工抛出异常,则此时需要throw关键字。
public static void main(String[] args) {
try {
throw new ArrayIndexOutOfBoundsException("\n我是手工异常:\n数组下标越界");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}
}
三、自定义异常类
为了处理各种异常,Java可通过继承的方式运行用户编写自己的异常类,因为所有可处理的异常均继承自Exception类,因此自定义异常类也不例外。
语法如下:
class 异常名称 extends Exception{
...
}
我们可以在自定义异常类里编写方法处理相关时间,甚至不编写任何语句也可以正常工作,因为父类Exception已提供相当丰富的方法,通过几次子类均可以使用它们。
static class MyException extends Exception{
public MyException(String msg){
super(msg);
}
}
public static void main(String[] args) {
try{
throw new MyException("自定义异常");
} catch (MyException e) {
e.printStackTrace();
System.out.println(e);
}
}
最后
前路漫漫啊,前路漫漫啊…
|