异常

本文深入探讨Java异常处理机制,包括异常的概念、分类、处理机制,以及throw和throws的区别。同时,介绍了如何通过try-catch-finally结构进行异常捕获与处理,并提供了自定义异常的示例。

一、Java异常处理

1.异常概念

    (1)什么是异常?

        所谓的异常是指在程序运行的过程中发生的一些不正常事件。(如:除0溢出,数组下标越界,所要读取的文件不存在。)

    (2)异常导致的后果?

        java程序在执行过程中如出现异常事件,可以生成一个异常类对象,该对象封装了异常事件的信息,并将其提交给java运行时系统,这个过程称为抛出异常,不处理的话会直接导致程序中断(即终止程序的进行)。

    (3)如何防止程序中断?

        设计良好的程序应该在程序异常发生时提供处理这些异常的方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果。

2.异常分类

(1)Error这种异常一般都是由java虚拟机生成并抛出的,包括动态链接的失败,虚拟机错误等等。程序对其一般不做任何处理,因为不是程序本身的问题,是系统(比如说虚拟机)的问题。就算你捕获了也没办法对其处理,所以一般不推荐对Error异常做任何的捕获或处理。

(2)Exception这种异常,一般需要用户或程序员显示声明获取捕获。

异常类型包括来源处理
受查异常(CheckedException)Exception及其子类(不包括RuntimeException及其子类)由代码控制能力之外的因素导致的运行时错误必须要处理,否则编译都通不过
非受查异常(UnCheckedException)Error和RuntimeException及其子类RuntimeException一般代表编程错误可以不用处理

3.java异常处理机制

(1)java的异常是通过两种机制来处理的:

    ①捕获异常:try---catch---finally

        try:监控区域,执行可能产生异常的代码

        catch:捕获,异常处理

        finally:善后处理,无论是否发生异常,代码总能执行(一般用来释放一些资源)

    ②抛出异常:throw、throws

4.try...catch...finally

(1)try{}语句块中放的是要检测的java代码,可能会抛出异常,也可能会正常执行。

(2)catch(异常类型){}块是当java代码运行时系统接收到try块中所抛出异常对象时,会寻找能处理这一异常catch块来进行异常处理(可以有多个catch块)。

(3)finally{}不管系统有没有抛出异常都会执行,一般用来释放资源。除了在之前执行了System.exit(0)【直接结束应用程序】

    如图所示:


实例:

public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("请输入一个数字");
        Scanner input = new Scanner(System.in);
        int res = 0;
        try {
            int num = input.nextInt();
            res = 10 / num;
        } catch (InputMismatchException e) { // 输入不匹配异常
            // e.getMessage()返回此Throwable的详细消息字符串

            System.out.println(e.getMessage());
            // 将此Throwable对象的堆栈跟踪输出至错误输出流,作为字段System.err的值
            e.printStackTrace();
        } catch (ArithmeticException e) { // 算术异常
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } finally {
            // 释放资源,比如关闭打开的文件,删除一些临时文件等。
            System.out.println("结果为:" + res);
            input.close();
        }
    }
}

①如果在try{}块中加入return(用来结束方法),finally块中的语句还会执行,即就算加了return,也会先执行完finally块再跳出方法。

②try块可以和catch块单独使用,也可以和finally块单独使用,也可以三者一起使用。和finally块一起使用时,它只关注自己所要做的事情,至于抛出异常,它自己不去捕获而是提交给调用相关方法的人去捕获。

③NullPointerException空指针异常:没有产生对象但却调用了对象里的相关方法或属性。

④在多catch块并存的情况下,安排catch语句的顺序时,首先应该捕获最特殊的异常,然后再逐渐一般化,即先子类后父类。

5.throw和throws

    (1)throw用于手动抛出异常。作为程序员可以通过throw这个关键字在任意位置手动抛出异常。

    (2)throws用于在方法上标识要暴露的异常。抛出的异常交由调用者处理(即throws修饰的方法,它本身内部不处理异常,而是交给调用此方法的那个人来处理这个方法所标识的异常类)。

     (3)两者区别:

            ① throw用在方法内抛出异常,后面跟上要抛出的异常类对象,一般是Exception这个类的子类异常。

            ② throws主要用来修饰方法,告诉调用者此方法可能会抛出异常,后面跟上可能要抛出的异常类名。


public class ExceptionDemo2 {
    public static void main(String[] args) {
        Bar bar = new Bar();
        bar.enter(15);
        System.out.println("END");
    }
}

class Bar {
    public void enter(int age) {
        if (age < 18) {
            throw new IllegalArgumentException("年龄不合格!");
        } else {
            System.out.println("欢迎光临!");
        }
    }
}

    注:这里程序没有打印输出end,因为在手动抛出异常的时候整个过程就中断了,那么我们不想让程序中断就应该捕获这个异常。这里没有捕获这个异常也没有报错,是因为这里抛出的是非受查异常,非受查异常可以不用捕获(这里说的不用捕获,指的是在抛出该非受查异常的地方可以不捕获这个异常,而不是调用此方法的地方),直接交给系统让系统自动检测,并将它们交给缺省的异常处理程序来处理。为了不让程序中断我们可以这样做:

public class ExceptionDemo2 {
    public static void main(String[] args) {
        Bar bar = new Bar();
        try {
            bar.enter(15);
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
        System.out.println("END");
    }
}

① 如果我们在方法中不想通过手动抛出一个异常,还可以通过在方法上通过throws关键字标明这个方法可能会抛出的异常,不管这个异常是受查异常还是非受查异常。即:

    public void enter(int age) throws IllegalArgumentException{...}

② 如果在方法中抛出Exception异常,即受查异常:throw new Exception("年龄不合格!");受查异常必须捕获(这里说的捕获指的是抛出该受查异常的地方),要么自己抛自己捕获,但这样做没有什么意义,一般往外抛,即在方法名后加throws Exception的方式告诉调用者,这个方法可能会抛出Exception这个异常,在调用的时候可以捕获这个异常或者继续往外抛。

public class ExceptionDemo2 {
    public static void main(String[] args) {
        Bar bar = new Bar();
        try {
            bar.enter(15);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println("END");
    }
}

class Bar {
    public void enter(int age) throws Exception {
        if (age < 18) {
            throw new Exception("年龄不合格!");
        } else {
            System.out.println("欢迎光临!");
        }
    }
}

总结: 当你手动抛出一个非受查异常的时候,可以不捕获,方法后面可以不加throws这个关键字。当你抛出的是一个受查异常,那么这个方法必须加throws关键字往外抛这个异常,而且调用这个方法的那条指令必须也要拿try{}来捕获或者不捕获也可以再往外抛,让调用主方法的人去捕获,否则就必须去捕获。往往throw和throws配合使用,以后在方法里面只要有throw,都要在方法后面加上throws,不管抛出的是受查异常还是非受查异常,这是一种写代码的规范。

6.自定义异常

  (1)常见异常

        ①受查异常:IOException、SQLException、ClassNotFoundException(不能加载请求的类)、NoSuchMethodException(请求的方法不存在)、InterruptedException(线程中断)FileNotFoundException(不能找到文件)、IllegalAccessException(对类的访问被拒绝)、EOFException(文件结束),需要捕获的异常,否则编译都通不过。

        ②非受查异常:RuntimeException(运行时异常,包括:类转换异常,数组下标越界,算术异常,非法参数异常,空指针异常,输入不匹配异常)

  (2)自定义异常类必须从已有的异常类继承(一般继承Exception),建立新的异常类型最简单的方法就是让编译器产生默认构造方法,对异常来说,最重要的部分就是它的类名,可以为异常类定义一个接受字符串参数的构造方法,这个字符串参数用来描述异常信息。


public class ExceptionDemo3 {
    public static void main(String[] args) {
        Bar bar = new Bar();
        try {
            bar.enter(15);
        } catch (AgeLessThanEighteenException e) {
            System.out.println(e.getMessage());
        }
        System.out.println("END");
    }
}

class AgeLessThanEighteenException extends Exception {
    
    private static final long serialVersionUID = 56153852936795919L;
    
    // 描述异常信息
    private String message = "";

    public AgeLessThanEighteenException(String message) {
        this.message = message;
    }
    
    @Override
    public String getMessage() {
        return message;
    }
    
}


class Bar {
    public void enter(int age) throws AgeLessThanEighteenException {
        if (age < 18) {
            throw new AgeLessThanEighteenException("年龄不合格!");
        } else {
            System.out.println("欢迎光临!");
        }
    }
}

案例讲解(医生给工人看病,工人在工作的过程中会生病,此时会抛出一个自定义异常。医生通过判断工人的状态,来给工人提供医治。)

public class ExceptionExample {
    public static void main(String[] args) {
        Worker worker = new Worker();
        Doctor doctor = new Doctor();
        try {
            worker.work();
        } catch (SickException e) {
            System.out.println(e.getMessage());
            doctor.cure(worker);
            if ("医治有效".equals(worker.getStatus())) {
                System.out.println("患者康复");
            } else {
                System.out.println(worker.getStatus());
                System.out.println("我们尽力了");
            }
        }
        System.out.println("欢迎下次来本院就诊");
    }
}

class SickException extends Exception {
    
    private static final long serialVersionUID = 9019785376733085852L;
    
    private String message = "";

    public SickException(String message) {
        this.message = message;
    }
    
    @Override
    public String getMessage() {
        return message;
    }
    
}

class Worker {
    // 工人的健康状态
    private String status = "";

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
    
    public void work() throws SickException{
        Random random = new Random();
        int rad = random.nextInt(3) + 1;
        // 用随机数来模拟工人生病
        if (rad == 1) {
            throw new SickException("生病了");
        } else {
            System.out.println("我很健康");
        }
    }
    
}

class Doctor{
    public void cure(Worker worker) {
        Random random = new Random();
        int rad = random.nextInt(2) + 1;
        // 使用随机数模拟医生看病结果
        if (rad == 1) {
            worker.setStatus("医治有效");
        } else {
            worker.setStatus("医治无效");
        }
    }
}

乐播投屏是一款简单好用、功能强大的专业投屏软件,支持手机投屏电视、手机投电脑、电脑投电视等多种投屏方式。 多端兼容与跨网投屏:支持手机、平板、电脑等多种设备之间的自由组合投屏,且无需连接 WiFi,过跨屏技术打破网络限制,扫一扫即可投屏。 广泛的应用支持:支持 10000+APP 投屏,包括综合视频、网盘与浏览器、美韩剧、斗鱼、虎牙等直播平台,还能将央视、湖南卫视等各大卫视的直播内容一键投屏。 高清流畅投屏体验:腾讯独家智能音画调校技术,支持 4K 高清画质、240Hz 超高帧率,低延迟不卡顿,能为用户提供更高清、流畅的视觉享受。 会议办公功能强大:拥有全球唯一的 “超级投屏空间”,扫码即投,无需安装。支持多人共享投屏、远程协作批注,PPT、Excel、视频等文件都能流畅展示,还具备企业级安全加密,保障会议资料不泄露。 多人互动功能:支持多人投屏,邀请好友加入投屏互动,远程也可加入。同时具备一屏多显、语音互动功能,支持多人连麦,实时语音交流。 文件支持全面:支持 PPT、PDF、Word、Excel 等办公文件,以及视频、图片等多种类型文件的投屏,还支持网盘直投,无需下载和转格式。 特色功能丰富:投屏时可同步录制投屏画面,部分版本还支持过触控屏或电视端外接鼠标反控电脑,以及在投屏过程中用画笔实时标注等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值