Java面向对象之异常处理

1、异常

1.1、问题引出
public static void main(String[] args) {
	int num1 = 10;
	int num2 = 0;
	int res = num1 / num2;
	System.out.println("程序继续运行....");
}
1.2、解决方案 — 异常捕获

对异常进行捕获,保证程序可以继续运行

package Exception01;

public class Exception01 {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;  // 可以使用Scanner() 获取;
        // 1. num1 / num2 => 10 / 0
        // 2. 当执行到 num1 / num2 因为 num2 = 0, 程序就会出现(抛出)异常 ArithmeticException
        // 3. 当抛出异常后, 程序就退出崩溃了, 下面的代码就不在执行
        // 4. 这样的程序设计不好, 不应该出现了一个不算致命的问题, 就导致整个系统崩溃
        // 5. java 设计者, 提供了一个叫 异常处理机制来解决该问题
        // int res = num1 / num2;
        // 如果程序员, 认为一段代码可能出现异常/问题, 可以使用 try-catch 异常处理机制来解决
        // 从而保证程序的健壮性
        // 将该代码块->选中->快捷键 ctrl + alt + t -> 选中 try-catch
        // 6. 如果进行异常处理, 那么即使出现了异常, 程序可以继续执行
        try {
            int res = num1 / num2;
        } catch (Exception e) {
            // e.printStackTrace();
            System.out.println("出现异常的原因=" + e.getMessage());  // 输出异常信息
        }
        System.out.println("程序继续运行....");
    }
}
1.3、定义

在这里插入图片描述

1.4、异常体系图一览
1.4.1、异常体系图

在这里插入图片描述

1.4.2、异常体系图的小结

在这里插入图片描述

1.5、常见的运行时异常
1.5.1、常见的运行时异常分类
  1. NullPointerException 空指针异常
  2. ArithmeticException 数学运算异常
  3. ArrayIndexOutOfBoundsException 数组下标越界异常
  4. ClassCastException 类型转换异常
  5. NumberFormatException 数字格式不正确异常
1.5.2、NullPointerException 空指针异常

当应用程序试图在需要对象的地方使用 null 时,抛出该异常

在这里插入图片描述

package exception_;

public class NullPointerException {
    public static void main(String[] args) {
        String name = null;
        System.out.println(name.length());
    }
}
1.5.3、ArithmeticException 数学运算异常

当出现异常的运算条件时,抛出此异常,例如,一个整数“除以零”时,抛出此类的一个实例

在这里插入图片描述

package exception_;

public class ArithmeticException {
    public static void main(String[] args) {
        int n1 = 100;
        int n2 = 0;
        System.out.println(n1 / n2);
    }
}
1.5.4、ArrayIndexOutOfBoundsException 数组下标越界异常

用非法索引访问数组时抛出的异常,如果索引为负或大于等于数组大小,则该索引为非法索引

在这里插入图片描述

package exception_;

public class ArrayIndexOutOfBoundsException_ {
    public static void main(String[] args) {
        int[] arrayList = {1, 2, 3, 4};
        for (int i = 0; i <= arrayList.length; i++) {
            System.out.println(arrayList[i]);
        }
    }
}
1.5.5、ClassCastException 类型转换异常

当试图将对象强制转换为不是实例的子类时,抛出该异常

在这里插入图片描述

package exception_;

public class ClassCastException_ {
    public static void main(String[] args) {
        A b = new B();  // 向上转型
        B b2 = (B) b;  // 向下转型
        C c2 = (C) b;  // 这里抛出 ClassCastException
    }
}

class A {}
class B extends A {}
class C extends A {}
1.5.6、NumberFormatException 数字格式不正确异常

当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常 => 使用异常我们可以确保输入是满足条件数字

在这里插入图片描述

package exception_;

public class NumberFormatException_ {
    public static void main(String[] args) {
        String str = "hello world";
        // 将 String 转成 int
        int num = Integer.parseInt(str);  // 抛出 NumberFormatException
        System.out.println(num);
    }
}
1.6、编译异常
1.6.1、定义

编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译

1.6.2、常见的编译异常

在这里插入图片描述

1.6.3、代码演示
package exception_;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Exception02 {
    public static void main(String[] args) {
        try {
            FileInputStream fis;
            fis = new FileInputStream("d:\\aa.jpg");
            int len;
            while ((len = fis.read()) != -1) {
                System.out.println(len);
            }
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2、异常处理

2.1、定义

异常处理就是当异常发生时,对异常处理的方式

2.2、异常处理的方式

在这里插入图片描述

2.3、示意图

在这里插入图片描述
在这里插入图片描述

2.4、try-catch 异常处理
2.4.1、定义

在这里插入图片描述

2.4.2、代码演示
package exception_;

public class ArithmeticException {
    public static void main(String[] args) {
        try {
            int n1 = 100;
            int n2 = 0;
            int res = n1 / n2;
        } catch (Exception e) {
            // e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}
2.4.3、注意事项

在这里插入图片描述

package exception_;

public class TryCatchDetail {
    public static void main(String[] args) {
        // ctrl + alt + t
        // 1. 如果异常发生了, 则异常发生后面的代码不会执行, 直接进入到 catch 块
        // 2. 如果异常没有发生, 则顺序执行 try 的代码块, 不会进入到 catch
        // 3. 如果希望不管是否发生异常, 都执行某段代码(比如关闭连接, 释放资源等)则使用如下代码- finally
        try {
            String str = "hello world";
            int a = Integer.parseInt(str);
            System.out.println("数字: " + a);
        } catch (NumberFormatException e) {
            System.out.println("异常信息=" + e.getMessage());
        } finally {
            System.out.println("finally 代码块被执行...");
        }
        System.out.println("程序继续...");
    }
}

在这里插入图片描述

package exception_;

public class TryCatchDetail02 {
    public static void main(String[] args) {
        // 1.如果 try 代码块有可能有多个异常
        // 2.可以使用多个 catch 分别捕获不同的异常, 相应处理
        // 3.要求子类异常写在前面, 父类异常写在后面
        try {
            Person person = new Person();
            // person = null;
            System.out.println(person.getName());  // NullPointerException
            int n1 = 10;
            int n2 = 0;
            int res = n1 / n2;  // ArithmeticException
        } catch (java.lang.NullPointerException e) {
            System.out.println("空指针异常=" + e.getMessage());
        } catch (java.lang.ArithmeticException e) {
            System.out.println("算术异常=" + e.getMessage());
        } catch (Exception e) {
            // e.printStackTrace();
            e.getMessage();
        } finally {
            System.out.println("我无论如何都会执行");
        }
    }
}

class Person {
    private String name = "jack";

    public String getName() {
        return name;
    }
}

在这里插入图片描述

package exception_;

public class TryCatchDetail03 {
    public static void main(String[] args) {
        /*
        可以进行 try-finally 配合使用, 这种用法相当于没有捕获异常,
        因此程序会直接崩掉/退出, 应用场景, 就是执行一段代码, 不管是否发生异常,
        都必须执行某个业务逻辑
        */
        try {
            int n1 = 10;
            int n2 = 0;
            System.out.println(n1 / n2);
        } finally {
            System.out.println("执行了 finally..");
        }
        System.out.println("程序继续执行..");
    }
}
2.4.4、try-catch-finally 执行顺序小结

在这里插入图片描述

2.4.5、代码演示

如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止

package exception_;

import java.util.Scanner;

public class TryCatchExercise04 {
    public static void main(String[] args) {
        // 如果用户输入的不是一个整数, 就提示他反复输入, 直到输入一个整数为止
        // 1. 创建 Scanner 对象
        // 2. 使用无限循环, 去接收一个输入
        // 3. 然后将该输入的值, 转成一个 int
        // 4. 如果在转换时, 抛出异常, 说明输入的内容不是一个可以转成 int 的内容
        // 5. 如果没有抛出异常, 则 break 该循环
        Scanner scanner = new Scanner(System.in);
        int num = 0;
        String inputStr = "";

        while (true) {
            System.out.print("请输入一个整数: ");
            inputStr = scanner.next();

            try {
                num = Integer.parseInt(inputStr);
                break;
            } catch (NumberFormatException e) {
                System.out.println("输入的类型不正确, 请重新输入!");
            }
        }
        System.out.println("num=" + num);
    }
}
2.5、throws 异常处理
2.5.1、定义

在这里插入图片描述
在这里插入图片描述

2.5.2、注意事项和使用细节

在这里插入图片描述

package throws_;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class ThrowsDetail {
    public static void main(String[] args) {
        f2();
    }

    public static void f2() /*throws ArithmeticException*/ {
        // 1.对于编译异常, 程序中必须处理, 比如 try-catch 或者 throws
        // 2.对于运行时异常, 程序中如果没有处理, 默认就是 throws 的方式处理
        int n1 = 10;
        int n2 = 0;
        double res = n1 / n2;
    }


    public static void f1() throws FileNotFoundException {
        // 这里大家思考问题 调用 f3() 报错
        // 1. 因为 f3() 方法抛出的是一个编译异常
        // 2. 即这时, 就要 f1() 必须处理这个编译异常
        // 3. 在 f1() 中, 要么 try-catch-finally, 或者继续 throws 这个编译异常
        f3();  // 抛出异常
    }

    public static void f3() throws FileNotFoundException {
        FileInputStream fis = new FileInputStream("d://aa.txt");
    }

    public static void f4() {
        // 1. 在 f4()中调用方法 f5() 是 OK
        // 2. 原因是 f5() 抛出的是运行异常
        // 3. 而 java 中, 并不要求程序员显示处理, 因为有默认处理机制
        f5();
    }

    public static void f5() throws ArithmeticException {
    }
}

class Father {  // 父类
    public void method() throws RuntimeException {
    }
}

class Son extends Father {  // 子类

    // 3. 子类重写父类的方法时, 对抛出异常的规定: 子类重写的方法,
    // 所抛出的异常类型要么和父类抛出的异常一致, 要么为父类抛出的异常类型的子类型
    //4. 在 throws 过程中, 如果有方法 try-catch, 就相当于处理异常, 就可以不必 throws
    @Override
    public void method() throws ArithmeticException {
    }
}
2.6、自定义异常
2.6.1、定义

在这里插入图片描述

2.6.2、自定义异常的步骤

在这里插入图片描述

2.6.3、代码实现

要求范围在 18 – 120 之间,否则抛出一个自定义异常

package throws_;

public class CustomException {
    public static void main(String[] args) {
        int age = 180;
        // 要求范围在 18 – 120 之间, 否则抛出一个自定义异常
        if (!(age >= 18 && age <= 120)) {
            //这里我们可以通过构造器,设置信息
            throw new AgeException("年龄需要在 18~120 之间");
        }
        System.out.println("你的年龄范围正确");
    }
}

// 自定义一个异常
// 1. 一般情况下, 我们自定义异常是继承 RuntimeException
// 2. 即把自定义异常做成运行时异常, 好处是我们可以使用默认的处理机制
// 3. 即比较方便
class AgeException extends RuntimeException {
    public AgeException(String message) {  // 构造器
        super(message);
    }
}
2.7、throw 和 throws 的区别

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值