Java异常复习

异常

异常:异常就是代表程序出现的问题

学习异常的目的就是学会程序出了异常之后,该如何处理

屏幕截图 2026-04-21 165549

Error:表示系统级别的错误(属于严重问题)

Exception:叫做异常,代表程序可能出现的问题。我们通常会用 Exception 以及他的子类来封装程序出现的问题

运行时异常:RuntimeException 及其子类,编译阶段不会出现异常提醒。运行时出现的异常(如:数组索引越界异常 ArrayIndexOutOfBoundsException)

编译时异常:编译阶段就会出现异常提醒的。(如:日期解析异常 ParseException)

package com.faxont.exception;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo1 {
    public static void main(String[] args) throws ParseException {

        // 编译时异常(在编译阶段,必须要手动处理,否则代码报错)
        String time = "2030年1月1日";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        Date date = sdf.parse(time);
        System.out.println(date);

        // 运行时异常(在编译阶段是不需要处理的,是代码运行时出现的异常)
        int[] arr = {1, 2, 3};
        System.out.println(arr[3]);// ArrayIndexOutOfBoundsException
    }
}

屏幕截图 2026-04-21 170835

编译时异常在于提醒程序员检查本地信息;而运行时异常是代码出错而导致程序出现的问题。

异常的作用

作用一:异常是用来查询 bug 的关键参考信息

作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况

异常的处理方式

JVM 默认的处理方式

  • 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
  • 程序停止执行,下面的代码不会再执行了

自己处理

捕获异常

// 格式
try {
    可能出现异常的代码;
} catch(异常类名 变量名) {
    异常的处理代码;
}

目的:当代码出现异常时,可以让程序继续往下执行。

package com.faxont.exception;

public class ExceptionDemo2 {
    public static void main(String[] args) {
        /*
            自己处理(捕获异常)
            格式:
                try {
                    可能出现异常的代码;
                } catch (异常类名 变量名) {
                    异常的处理代码;
                }
         */

        int[] arr = {1, 2, 3, 4, 5, 6};

        try{
            // 可能出现的异常的代码
            /**
             * 此处出现了异常,程序就会在这里创建一个 ArrayIndexOutOfBoundsException 异常对象
             * new ArrayIndexOutOfBoundsException();
             * 拿着这个对象到 catch 的小括号中对比,看括号中的变量是否可以接收这个对象
             * 如果能被接收,就表示该异常被捕获,执行 catch 里面对应的代码
             * 当 catch 里面所有的代码执行完毕,继续执行 try ... catch 体系下面的其它代码
             */
            System.out.println(arr[10]);
        }catch(ArrayIndexOutOfBoundsException e){
            // 如果出现了 ArrayIndexOutOfBoundsException 异常,就执行这个 catch 中的代码
            System.out.println("数组越界异常");
        }

        System.out.println("程序继续执行");
    }
}

灵魂四问

  1. 如果 try 中没有遇到问题,怎么执行?

会把 try 里面所有的代码全部执行完毕,不会执行 catch 里面的代码。

  1. 如果 try 中可能会遇到多个问题,怎么执行?

解决:会写多个 catch 与之对应。

如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面。

在 JDK7 之后,我们可以在 catch 中同时捕获多个异常,中间用 | 隔开;

表示如果出现了 A 异常或者 B 异常的话,采取同一处理。

  1. 如果 try 中遇到的问题没有被捕获,怎么执行?

相当于 try ... catch 的代码白写了,最终还是会交给虚拟机进行处理。

  1. 如果 try 中遇到了问题,那么 try 下面的其它代码还会执行吗?

下面的代码就不会执行了,直接跳转到对应的 catch 当中,执行 catch 里面的语句体;

但是如果没有对应的 catch 与之匹配,那么还是会交给虚拟机进行处理。

抛出异常

throws

注意:写在方法定义处,表示声明一个异常,告诉调用者,使用本方法可能会有哪些异常

public void 方法() throws 异常类名1, 异常类名2 ...{
    ...
}
  • 编译时异常:必须要写。
  • 运行时异常:可以不写。

throw

注意:写在方法内,结束方法,手动抛出异常对象,交给调用者,方法中下面的代码不再执行了

public void 方法(){
    throw new NullPointerException();
}
package com.faxont.exception;

public class ExceptionDemo4 {
    public static void main(String[] args) {
        /*
            throws : 写在方法定义处,表示声明一个异常,告诉调用者,使用本方法可能会有哪些异常
            throw : 写在方法内,结束方法,手动抛出异常对象,交给调用者,方法中下面的代码不再执行了

            需求:
                定义一个方法求数组的最大值
         */

        int[] arr = {1, 2, 3, 4, 5};
        int[] arrNull = null;
        int[] arrEmpty = new int[0];

        System.out.println(getMax(arr));
        try {
            System.out.println(getMax(arrNull));
        } catch (NullPointerException e) {
            System.err.println("空指针异常");
        }
        try {
            System.out.println(getMax(arrEmpty));
        } catch (ArrayIndexOutOfBoundsException e) {
            System.err.println("数组索引越界异常");
        }

    }

    // NullPointerException 和 ArrayIndexOutOfBoundsException 都是运行时异常,即 RuntimeException 的子类,运行时异常可以省略不写
    public static int getMax(int[] arr) /*throws NullPointerException, ArrayIndexOutOfBoundsException*/{
        if(arr == null){
            // 手动创建一个异常对象,并把这个异常交给方法的调用者处理
            // 此时方法就会结束,下面的代码不会再执行了
            throw new NullPointerException("数组不能为null");
        }
        if(arr.length == 0){
            // 手动创建一个异常对象,并把这个异常交给方法的调用者处理
            // 此时方法就会结束,下面的代码不会再执行了
            throw new ArrayIndexOutOfBoundsException("数组不能为空");
        }
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if(max < arr[i]){
                max = arr[i];
            }
        }
        return max;
    }
}

Throwable 的成员方法

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

public class ExceptionDemo3 {
    public static void main(String[] args) {
        /*
            public String getMessage()          返回此 throwable 的详细消息字符串
            public String toString()            返回此可抛出的简短描述
            public void printStackTrace()       把异常的错误信息输出在控制台(仅仅是打印信息,不会停止程序运行)
         */

        int[] arr = {1, 2, 3, 4, 5, 6};

        try {
            System.out.println(arr[10]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println(e.getMessage());
            System.out.println(e.toString());
            e.printStackTrace();// 最常用的,因为其所包含的信息是最多的
        }

        System.out.println("程序继续执行...");

        // 正确的输出语句
        System.out.println("123");

        // 错误的输出语句(输出错误信息的输出语句)
        // 打印出来的顺序不是固定的,有可能跟代码顺序不一样
        System.err.println("123");// 输出的字符是红色的,跟平时看到的错误信息是一样的
    }
}

练习:键盘录入数据

需求:

​ 键盘录入自己的姓名和年龄

​ 姓名的长度在 3 ~ 10 之间

​ 年龄的范围为 18 ~ 40 岁,

​ 超出这个范围视为异常数据,不能赋值需要重新录入,直到正确为止。

提示:

​ 需要考虑用户在键盘录入时的所有情况。

​ 比如:录入年龄时超出范围,录入年龄时录入了 abc 等情况

package com.faxont.exception;

import java.util.InputMismatchException;
import java.util.Scanner;

public class ExceptionDemo5 {
    public static void main(String[] args) {
        /*
            需求:
            键盘录入自己的姓名和年龄
            姓名的长度在 3 ~ 10 之间
            年龄的范围为 18 ~ 40 岁,
            超出这个范围视为异常数据,不能赋值需要重新录入,直到正确为止。
            提示:
            需要考虑用户在键盘录入时的所有情况。
            比如:录入年龄时超出范围,录入年龄时录入了 abc 等情况
         */

        // 创建 Scanner 对象
        Scanner sc = new Scanner(System.in);

        // 创建 Person 对象
        Person p = new Person();

        while (true) {
            try {
                // 录入姓名
                System.out.println("请输入自己的姓名:");
                String name = sc.next();
                p.setName(name);

                // 录入年龄
                System.out.println("请输入自己的年龄:");
                int age = sc.nextInt();
                p.setAge(age);

                // 全部正确,录入成功,打印出录入结果
                System.out.println("录入成功!" + p);
                break;

            } catch (InputMismatchException e){
                System.out.println("请输入数字!");
                sc.next();// 输入错误,需要清空输入缓冲区

            } catch (RuntimeException e) {
                // 捕获自定义异常信息
                e.printStackTrace();
            }

        }
    }
}
package com.faxont.exception;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        // 验证姓名长度是否符合规范
        if (name.length() < 3 || name.length() > 10) {
            throw new NameFormatException("姓名长度必须在 3 ~ 10 之间,请重新输入!");
        }
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        // 验证年龄是否符合规范
        if (age < 18 || age > 40) {
            throw new AgeOutOfException("年龄范围必须在 18 ~ 40 岁之间,请重新输入!");
        }
        this.age = age;
    }

    public String toString() {
        return "姓名:" + name + ", 年龄:" + age;
    }
}

自定义异常

意义:就是为了让控制台的报错信息更加的清晰

  1. 定义异常类

  2. 写继承关系

  3. 空参构造

  4. 带参构造

package com.faxont.exception;

public class NameFormatException extends RuntimeException{
    // 技巧:
    // NameFormat:当前异常的名字,表示姓名格式化问题
    // Exception:表示当前类是一个异常类

    // 运行时:RuntimeException 核心 就表示由于参数错误而导致的问题
    // 编译时:Exception 核心 提醒程序员检查本地信息

    public NameFormatException() {
    }

    public NameFormatException(String message) {
        super(message);
    }
}
package com.faxont.exception;

public class AgeOutOfException extends RuntimeException{
    public AgeOutOfException() {
    }

    public AgeOutOfException(String message) {
        super(message);
    }
}
posted @ 2026-04-21 20:04  弋湖  阅读(3)  评论(0)    收藏  举报