其他分享
首页 > 其他分享> > 第六章 异常机制

第六章 异常机制

作者:互联网

第六章 异常机制

1 什么是异常(exception)

1.1 异常的简单分类

异常可大致分为三类:

  1. 一般性异常(受控异常):这种异常属于一般性异常,出现了这种异常必须显示的处理,不显示处理java程序将无法编译通过。编译器强制普通异常必须try…catch处理,或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常编译期就必须处理的,否则程序不能通过编译,就更不能正常运行了

  2. 运行时异常(非受控异常):非受控异常也即是运行时异常(RuntimeException),这种系统异常可以处理也可以不处理,所以编译器不强制用try…catch处理或用throws声明,所以系统异常也称为unchecked异常在编译期是不检查的,出现问题后,需要我们回来修改代码

    此种异常可以不用显示的处理,例如被0除异常,java没有要求我们一定要处理, 当出现这种异常时,肯定是程序员的问题,也就是说,健壮的程序一般不会出现这种系统异常。

  3. 错误(ERROR:如果应用程序出现了Error,那么将无法恢复,只能重新启动应用程序,最典型的Error的异常是:OutOfMemoryError

2 异常体系结构

image

2.1 Error

2.2 Exception

3 异常的处理

【注】代码块生成快捷键:选中要包裹代码块的代码,crtl+alt+t

image

为什么要自己处理异常

JVM默认的异常处理方案是遇到异常就结束程序的运行,而在实际的开发中,遇到了异常不应该影响后续的程序运行。

异常处理方式

运行时异常(系统异常)不需要预处理,通过规范的代码可以避免产生这种异常
受检异常(编译时异常)必须预处理,否则编译报错,有两种预处理方式 :

3.1 异常捕获处理

3.1.1 try、catch和finally

异常的捕获和处理需要采用try和catch来处理,具体格式如下:

try {

} catch (OneException e) {

} catch (TwoException e) {

} finally {

}	
try{
    
}finally{
    
}

3.1.2 异常捕获处理

异常捕获处理详细说明:

private static void testException2() {
    try {
        //1、对可能产生异常的代码进行检视
        //2、如果try代码块的某条语句产生了异常, 就立即跳转到catch子句执行, try代码块后面的代码不再执行
        //3、try代码块可能会有多个受检异常需要预处理, 可以通过多个catch子句分别捕获
    } catch (异常类型1 e1) {
        //捕获异常类型1的异常, 进行处理
        //在开发阶段, 一般的处理方式要么获得异常信息, 要么打印异常栈跟踪信息(e1.printStackTrace())
        //在部署后, 如果有异常, 一般把异常信息打印到日志文件中, 如:logger.error(e1.getMessage());
    } catch (异常类型2 e1) {
        //捕获异常类型2的异常, 进行处理
        //如果捕获的异常类型有继承关系, 应该先捕获子异常再捕获父异常
        //如果没有继承关系, catch子句没有先后顺序
    } finally {
        //不管是否产生了异常, finally子句总是会执行
        //一般情况下, 会在finally子句中释放系统资源
    }
}

【代码示例】

若不进行try-catch处理,JVM的默认异常处理方法:

package com.exception.demo01;

public class ExceptionDemo01 {
    public static void main(String[] args) {
        System.out.println("开始");
        method();
        System.out.println("结束");
    }

    public static void method(){
        int[] arr = {1,2,3};
        System.out.println(arr[3]);
    }
}

执行结果:结果只输出了“开始”没有输出“结束”,即JVM遇到异常默认结束程序运行

image

进行try-catch处理

package com.exception.demo01;

public class ExceptionDemo01 {
    public static void main(String[] args) {
        System.out.println("开始");
        method();
        System.out.println("结束");
    }

    public static void method(){
        try {
            int[] arr = {1,2,3};
            System.out.println(arr[3]);//自动抛出了异常对象,相当于进行了new ArrayIndexOutOfBoundsException();操作,再把这个新创建的对象给到下面的e
        } catch (ArrayIndexOutOfBoundsException e) {
            //System.out.println("你访问的索引不存在");//实际开发不会直接输出一句话,而是给出一个页面提示
            e.printStackTrace();//打印错误的栈信息
        }
    }
}

执行结果:结果输出了“开始”和“结束”,遇到异常程序正常运行

image

3.1.3 异常的捕获顺序

异常的捕获:一般按照由小到大的顺序,也就是先捕获子异常,再捕获父异常

package com.exception;

public class Demo01 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        try {//try监控区
            System.out.println(a/b);
        } catch (ArithmeticException ae){//catch用作捕获异常,格式:catch(想要捕获的异常类型)
            System.out.println("程序出现异常,变量b不能为0");
        } catch (Exception e){
            System.out.println("Exception");
        } catch (Throwable t){
            System.out.println("Throwable");
        } finally {//finally处理善后工作
            System.out.println("finally");
        }
        /*finally可以不要,但try和catch一定要有,
        可以捕获多个异常即catch可以有多个,捕获的异常要从小到大,也就是先截获子异常,再截获父异常*/
    }
}

3.2 Throwable的成员方法

方法名 说明
public String getMessage() 返回此throwable的详细消息字符串
public String toString() 返回此可抛出的简短描述
public void printStackTrace() 把异常的错误信息输出在控制台

三个成员方法的输出示例:

代码部分:

package com.exception.demo01;

public class ExceptionDemo01 {
    public static void main(String[] args) {
        System.out.println("开始");
        method();
        System.out.println("结束");
    }

    public static void method(){
        try {
            int[] arr = {1,2,3};
            System.out.println(arr[3]);
        } catch (ArrayIndexOutOfBoundsException e) {
            //System.out.println(e.getMessage());
            //System.out.println(e.toString());
            //e.printStackTrace();
        }
    }
}

输出结果:

getMessage():返回此throwable的详细消息字符串

image

toString()(返回异常的类名和异常原因):返回此可抛出的简短描述

image

printStackTrace()(显示异常类名、异常原因、异常位置,异常信息最详细,所以一般都用这个方法来把异常信息显示在控制台):把异常的错误信息输出在控制台

image

3.2.1 getMessage()printStackTrace()

如何取得异常对象的具体信息,常用的方法主要有两种:

✳值得一提的是✳

getMessage()的功能是返回异常原因,其返回的值是detaiMessage也就是Throwable类中有参构造中传递的message

Throwable类中的方法getMessage()的源码简单可概括为以下:

public class Throwable{
    private String detailMessage;
    
    public Throwable(String message){
        detailMessage = message;
    }
    
    public String getmessage(){
        return detailMessage;
    }
}

可以看出getMessage()的功能就是获取在初始化Throwable的某个Exception子类对象时传给此子类构造器的message,此子类的有参构造器又会调用其父类的有参构造,直到将message赋值给detailMessage,也就是getMessage()返回的detailMessage

3.3 throws抛出处理

虽然我们通过try-catch可以对异常进行处理,但是并不是所有的情况我们都有权限进行异常的处理,也就是说,有些时候可能出现的异常是我们处理不了的,这个时候该怎么办呢?

针对这种情况,Java提供了throws 的处理方案。抛出异常只是延迟了异常的处理,并没有解决异常。

格式:throws 类名【注意】这个格式是跟在方法的括号后面的。

【小结】:


在定义方法时,如果方法体中有受检(编译时)异常需要预处理,可以捕获处理,也可以抛出处理

处理异常时,使用throws抛出处理:

4 自定义异常

为什么要学习自定义异常?

虽然Java提供了很多异常类供我们使用,但是实际开发中并不能满足我们所有的需求。

示例:

ScoreException自定义异常类:

package com.exception.demo01;

public class ScoreException extends Exception {
    public ScoreException(){}

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

Teacher类:

package com.exception.demo01;

public class Teacher {

    public void checkScore(int score) throws ScoreException{
        if (score<0 || score>100){
            throw new ScoreException("你给的分数有误,分数在0-100间");//自定义异常需要自己用throw抛出异常对象,给出提示信息,像是普通的异常会自动抛出异常对象。此处要是括号无内容即调用无参构造,在控制台就不会输出异常提示内容
        }else {
            System.out.println("输出正常");
        }
    }
}

main方法:

package com.exception;

import com.exception.demo01.ScoreException;
import com.exception.demo01.Teacher;

import java.util.Scanner;

public class Application {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入分数:");
        int score = scanner.nextInt();

        Teacher t = new Teacher();
        try {
            t.checkScore(score);
        } catch (ScoreException e) {
            e.printStackTrace();
        }
    }
}

4.1 throw与throws

throws throw
用在方法声明后面,跟的是异常类名 用在方法体内,跟的是异常对象名
表示抛出异常,由该方法的调用者来处理 表示抛出异常,由方法体内的语句处理
表示出现异常的一种可能性,并不一定会发生这些异常(例如上文中Teacher类中的checkScore()方法若是0-100分就不会出现异常) 执行throw一定抛出了某种异常(例如上文中Teacher类中的checkScore()方法只要执行了throw语句证明一定出现了异常)

throw 和 throws 的区别?

标签:处理,System,try,catch,第六章,机制,异常,public
来源: https://www.cnblogs.com/Ayisprite/p/16146334.html