java笔记_异常处理

什么是异常?Java代码在运行时期发生的问题就是异常。在Java中,把异常信息封装成了一个类。当出现了问题时,就会创建异常类对象并抛出异常相关信息(如异常出现的位置、原因等)。

异常处理机制

Java的异常处理机制可以让程序具有记号的容错性,使程序更加的健壮。当程序运行出现意外情形时门系统会自动生成一个Exception对象来通知程序。

异常的继承体系

Throwable: 它是所有错误与异常的超类(祖宗类)
    |- Error 错误
    |- Exception 编译期异常,进行编译JAVA程序时出现的问题
        |- RuntimeException 运行期异常, JAVA程序运行过程中出现的问题

异常与错误的区别

异常:指程序在编译、运行期间发生了某种异常(XxxException),我们可以对异常进行具体的处理。若不处理异常,程序将会结束运行。

错误:指程序在运行期间发生了某种错误(XxxError),Error错误通常没有具体的处理方式,程序将会结束运行。Error错误的发生往往都是系统级别的问题,都是jvm所在系统发生的,并反馈给jvm的。我们无法针对处理,只能修正代码。

throw/throws关键字

如果一个方法没有捕获到一个检查性异常,那么该方法必须使用throws关键字来声明。throws关键字放在方法签名的尾部。也可以使用throw关键字抛出一个异常。

1)抛出异常 throw

格式:

throw new 异常类名(参数);

示例:

public static int getElement(int[] arr, int index){
    if( arr == null){
        throw new NULLPointException("arr指向的数组不存在");
    }
    if( index<0 || index>=arr.length ){
        throw new ArrayIndexOutOfBoundsException("错误的角标, "+ index +"索引在数组中不存在");
    }
}

2)声明异常 throws

格式:

修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2,... {}

示例:

public static int getElement(int[] arr,int index) throws NullPointerException,ArrayIndexOutOfBoundsException {
    if( arr==null ){
        throw new NullPointerException("arr指向的数组不存在");
    }
    if( index<0 || index>=arr.length ){
        throw new ArrayIndexOutOfBoundsException("错误的角标, " + index + "索引在数组中不存在");
    }
}

捕获异常try…catch…finally

捕获:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。

格式:

try{
    //需要被检测的语句
}catch(异常类 变量){
    //异常的处理语句
}finally{
    // 一定会被执行的语句
}

try:该代码块中编写可能产生异常的代码。
catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。
finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

示例:

class ExceptionDemo{
    public static void main(String[] args){
        try{
            int[] arr = new int[3];
            System.out.println( arr[5] ); //会抛出ArrayIndexOutOfBoundsException
            // 当产生异常时,必须有处理方式。要么捕获,要么声明。
        } catch (ArrayIndexOutOfBoundsException e){
            System.out.println("异常发生了");
        } finally {
            arr = null; // 把数组指向null, 通过垃圾回收器,进行内存垃圾的清楚
        }
        System.out.println("程序运行结果");
    }
}

try…catch…finally异常处理的组合方式

1)try catch finally组合:检测异常,并传递给 catch 处理,并在finally中进行资源释放。
2)try catch 组合:对代码进行异常检测,并对检测的异常传递给catch处理。对异常进行捕获处
理。

示例:

void show(){
    try{
        throw new Exception(); //产生异常,直接捕获处理
    } catch(Exception e){
        //处理方式
    }
}

3)一个try多个catch组合:对代码进行异常检测,并对检测的异常传递给catch处理。

示例:

void show(){
    try{
        throw new Exception(); // 产生异常,直接铺货处理
    }catch(XxxException e){
        // 处理方式
    }catch(YyyException e){
        // 处理方式
    }catch(ZzzException e){
        // 处理方式
    }
}

注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

4)try finally组合:对代码进行异常检测,检测到异常后因为没有catch,所以一样会被默认jvm抛出。异常是没有捕获处理的。但是功能所开启资源需要进行关闭,所有finally只为关闭资源。

示例:

void show(){
    try{
        throw new Exception();
    }finally{
        //释放资源
    }
}

运行时期异常

1)RuntimeException 和他的所有子类异常,都属于运行时期异常。

NullPointerException,ArrayIndexOutOfBoundsException等都属于运行时期异常.

2)运行时期异常的特点:

方法中抛出运行时期异常,方法定义中无需throws声明,调用者也无需处理此异常

运行时期异常一旦发生,需要程序人员修改源代码

 class ExceptionDemo{
    public static void main(String[] args){
        method();
    }
    public static void method(){
        throw new RuntimeException();
    }
}

异常在方法重写中细节

1)子类覆盖父类方法时,如果父类的方法声明异常,子类只能声明父类异常或者该异常的子类,或者不声明。

class Fu {
    public void method() throws RuntimeException{
    }
}
class Zi extends Fu{
    public void method() throws RuntimeException {} //抛出父类一样的异常
    // public void method() throws NullPointerException{} // 抛出符类子异常
}

2)当父类方法声明多个异常时,子类覆盖时只能声明多个异常的子集。

class Fu{
    public void method() throws NullPointerException,ClassCastException{
    }
}
class Zi extends Fu{
    public void method() throws NullPointException,ClassCastException{}
    public void methods() throws NullPointException{} //抛出父类异常中的一部分
    public void methods() throws ClassCastException{} //抛出父类异常中的一部分
}

3)当被覆盖的方法没有异常声明时,子类覆盖时无法声明异常的。

class Fu{
    public void method(){
    }
}
class Zi extends Fu{
    public void method() throws Exception{} //错误的方式
}

异常中常用方法

异常类说明
ClassCastException类型转换异常
ClassNotFoundException未找到相应类异常
ArithmeticException算术异常
ArrayIndexOutOfBoundsException数组下标越界异常
ArrayStoreException数组中包含不兼容的值抛出的异常
SQLException操作数据库异常类
NullPointerException空指针异常
NoSuchFieldException字段未找到异常
NoSuchMethodException方法未找到抛出的异常
NumberFormatException字符串转换为数字抛出的异常
NegativeArraySizeException数组元素个数为负数抛出的异常
StringIndexOutOfBoundsException字符串索引超出范围抛出的异常
IOException输入输出异常
IllegalAccessException不允许访问某类异常
InstantiationException当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
EOFException文件已结束异常
FileNotFoundException文件未找到异常

自定义异常

java中所有的异常类,都是继承Throwable,或者继承Throwable的子类。这样该异常才可以被throw抛出。

格式:

Class 异常名 extends Exception{  // 或继承 RuntimeException
    public 异常名(){
    }
    public 异常名(String s){
        super(s);
    }
}

1、自定义异常继承Exception示例:

class MyException extends Exception{
    public MyException(){
        super();
    }
    public MyException(String message){
        super(message);
    }
}

2、自定义异常继承RuntimeException示例:

class MyException extends RuntimeException{
    MyException(){
        super();
    }
    MyException(String message){
        super(message);
    }
}

异常处理规则

1、不要过度使用异常

异常只应该用于处理非正常的情况,不要使用异常处理来代替正常的流程控制。对于一些完全可预知,而且处理方式清楚的错误,程序应该提供相应的错误处理代码,而不是将其笼统地称为异常。

2、不要使用过于庞大的tyr块

try块里的代码过于庞大,业务过于复杂,会使得try块中出现异常的可能性大大增加,从而导致分析异常原因的难度也大大增加。

正确做法:分割成多个可能出现的异常程序段落,并放在单独的try块中,分别捕获并处理异常。

3、不要忽略捕获到的异常

1)处理异常:对异常进行合适的修复,绕过异常发生的地方继续执行

2)重新抛出新异常:把异常包装成当前层的异常,重新抛出给上层调用者

3)在合适的层处理异常:不清楚如何处理异常,就不要在当前层使用catch来捕获,直接使用throws声明抛出该异常,让上层调用者来负责处理该异常。

-------------本文结束感谢您的阅读-------------
Mr.wj wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!