Java中的异常

我们在编程的过程中,经常会遇到异常,比如除0异常、空指针异常、数组下标越界异常、并发修改异常,还有类型转换异常,这些都是我们平时非常容易见到的,使用一个数除以0的时候就会出现除0异常,声明一个String对象为null,然后再使用它去调用String对象的方法,那就会报空指针异常,声明一个长度为5的数组,却去访问这个数组第8个元素,当然就会出现数组下标越界异常,遍历集合的时候,先是委托给迭代器去循环遍历,而我们又在循环体当中使用集合对元素进行操作,这时候就会出现并发修改异常,而最后一种,两个没有什么关系的猴子类和学生类,在编程的过程中却想将猴子对象转为学生类对象,那当然就会出现类型转换异常了,所以,异常在平常开发中是十分常见的。

1.除0异常
2.空指针异常
3.数组下标越界异常
4.并发修改异常
5.类型转换异常

1.分类

Java中异常的超类是Throwable,它可以分为两类:错误(Error)和异常(Exception),而错误我们是不用管的,因为我们处理不了,一般我们需要处理的就是Exception(异常),而异常又可以分为两类:编译时期异常和运行时异常(RuntimeException),编译时期异常是在编译的时候就会给出异常提示信息,这时就需要在抛出异常的方法的方法声明上抛出异常或者将可能会抛出异常的语句使用try…catch语句包围起来。而运行时异常则不用。平时开发过程中,我们也可以根据需要写出自己的异常类,只要继承Exception或者RuntimeException就可以了

Throwable
    Error
    Exception
        编译时期异常
        RuntimeException(运行时期异常)

2.对异常的处理

对异常的处理分为两类,第一类是向上抛出,即向方法的调用者抛出,当然不可能无限向上抛出,实际情况是如果一直都是抛出的话,就会顺着调用方法的路径一直到main方法,而main方法上也是抛出的话,那就会抛出给虚拟机,而虚拟机就会让程序停止运行了;第二类就是对可能抛出异常的代码块使用try…catch代码块包围起来处理。

1.将异常一直向上抛出,直到虚拟机为止
2.将可能抛出异常的代码块使用try...catch语句包围起来处理

2.1 方法声明中抛出异常

第一种直接抛出异常的话只需要在可能出现异常的方法的方法声明上使用throws关键字抛出相应的异常就可以了。

public static void main(String[] args) throws ArithmeticException {
    System.out.println(2 / 0);
}

2.2 使用try…catch语句处理异常

处理异常的规则是将可能出现异常的代码块放到try语句块中,然后在catch中写出可能出现的异常类,并给出处理措施,当在try语句块中的代码真的发生异常时,它就会根据所发生异常的类型去和catch语句块中的异常进行配对,找到对应的便执行对应异常类的处理措施,这个就和if…else if很像了,都是去进行配对,然后找相对应的去执行,当然catch的后面其实还可以加finally语句块的,它的作用是什么呢?就是不管前面try和catch语句块中发生什么,finally中的语句一定会执行,这在实际开发中也很有用,比如使用IO流的时候最后一定要关闭IO流,数据库的连接最后使用完了之后也一定要关闭。

catch代码块中各个异常类的放置位置也是有要求的,最好将父类放在后面,因为在匹配异常的时候,是从头往后匹配的,匹配一个之后就不会再匹配了,因此应该将表示范围大的异常放在后面,同级别的异常放置位置则没有要求。

try {
    String s = null;
    System.out.println(s.length());
    int[] arr = new int[5];
    System.out.println(arr[7]);
} catch (NullPointerException e) {
    System.out.println("空指针异常");
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("数组下标越界异常");
} catch (Exception e) {
    System.out.println("出异常了");
}finally{
    System.out.println("一定会执行");
}

3.自定义异常

Java是允许我们自定义异常的,那为什么要自己定义异常呢?举个例子,当我们的程序在操作数据库时发生异常时,如果直接抛出的是数据库异常,并显示在了用户界面上,用户是不一定能看得懂的,这就会降低界面友好型,而且将数据库异常直接显示,也不能保证系统的安全性。如果我们能自定义异常,在操作数据库发生异常时,抛出的是我们自己定义的异常,那我们就能给出自己的提示信息,保证了用户界面的友好型,也维护了系统的安全。

那如何才能自定义异常呢?其实很简单,只需要创建一个类,然后继承Exception或者RuntimeException就好了,其实RuntimeException也是继承的Exception,当直接继承Exception这个类时,那说明我们定义的类是编译时期异常类,而如果继承的是RuntimeException的话,那就说明是运行时期异常类,声明好类的继承之后,还需要重写父类的两个构造函数,一个有参,一个无参,其中传入参数的是这个异常发生的原因。

class MyException extends Exception {

    public MyException() {
        super();
    }

    public MyException(String message) {
        super(message);
    }
}

如果声明的是编译时期异常,那就必须在可能出现异常的方法的方法声明上使用throws抛出异常。

public static void checkScore(int score) throws MyException {
    if(score<0 || score>100){
        throw new MyException("分数不符合要求!");
    }
    System.out.println("分数符合要求");
}

而如果是声明的运行时期异常,那就不用了

class MyException extends RuntimeException {

    public MyException() {
        super();
    }

    public MyException(String message) {
        super(message);
    }
}

那调用的时候像下面这样就好了

public static void checkScore(int score) {
    if(score<0 || score>100){
        throw new MyException("分数不符合要求!");
    }
    System.out.println("分数符合要求");
}

4.总结

感觉把知识点整理一遍,心里还是有底一点,不整理虽然知道,但总感觉还是模糊的,在自己总结一遍的时候,起码又过了一遍,写文章的时候,也会自己去感觉哪里是重点,会更重要一点,写下来也会有个取舍,写的东西也许不是很深入,那就相当于是给以后打个基础吧,期待以后补强。

坚持原创技术分享,您的支持将鼓励我继续创作!