Java中的异常处理(基础解析一)

本文详细介绍了Java中的异常处理机制,包括异常的基本概念、异常的几种常见类型(如空指针异常、越界异常、算术异常),如何使用try...catch...finally进行异常处理,以及运行时异常和编译时异常的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异常处理

Throwable

    Throwable是异常最顶端的类
    它的子类:Error(服务器崩溃 数据库崩溃)
             Exception(异常类)
             Exception中最常见的就是:RuntimeException(运行时异常)
    异常的几种类型:
        空指针异常:
            int[] array = new int[4];
            array = null;
            System.out.println(array[1]);

            运行程序时,会报空指针异常
            NullPointerException(空指针)

            空指针异常也就是访问了一块不属于我的空间
        越界异常:
            int[] array = new int[4];
            System.out.println(array[5]);

            运行时会报,越界异常
            ArrayIndexOutOfBoundsException(越界异常)
            越界异常就是你打印的这个角标大于这个数组的长度
        算术异常
        System.out.println(10/0);

        运行时,会报算术异常
        ArithmeticException
        算术异常是一个数除以0,就会报算术异常
    出现异常该如何解决?
        1.出现异常要去找上级解决
        2.找上级解决相当于找 任务的调用者
            main函数的调用者 JVM去处理
        3.JVM默认的处理方式:
            打印异常类 错误信息 和 错误发生的位置
            直接停止程序
    除了让系统自己处理异常外,我们自己也可以处理异常

    使用try...catch...finally 方法
        try:   指测试异常代码
        catch: 指捕获异常信息
        finally指一场结束后 要做的事情

        这里我们创建一个测试异常的类

    class TestException{
        //除法 返回两个数的商
        public int fun(int a,int b){
            //这一句代码可能会发生异常
            //例如 一个数 除以0 就会发生
            //算术异常错误
            //ArithmeticException
            return a / b;
        }
    }
    public class Demo {
        public static void main(String[] args) {
            //创建一个测试异常类的对象
            TestException test = new TestException();
            try{
                //可能发生异常的代码
                int num = test.fun(5, 0);
            }catch (ArithmeticException e){
                //捕获异常 捕获到的是什么?
                //捕获到的是这个异常类的对象
                //相当于
                //ArithmeticException e = new ArithmeticException();
                //所以小括号中要放 捕获到的是什么异常
                System.out.println("你除数 为 0");
            }
            System.out.println("哈哈");
        }
    }

    程序执行完后打印的结果: 你除数为0
                            哈哈

    为什么"哈哈"也会被打印?
    因为catch捕获到了 try中的异常后 程序继续运行
    所以"哈哈"也会被打印
    如果fun中除数不是0,就会打印 num 和 "哈哈"
try…catch捕获异常的流程
    1.函数中 某句代码 发生异常
    2.发生异常 就产生了异常对应的 异常对象
    3.这个异常对象 返回给调用者
        1)调用者没有对异常进行处理
        这时就会把异常交给上级,交给JVM去处理
        JVM就会使用默认的处理方式
        2)调用者进行异常处理(使用try...catch)
        这时返回的异常对象会跟catch进行匹配
        如果匹配成功就会执行catch中的语句
        程序还是会继续运行

多catch处理异常

    int[] array = new int[4];
    try{
        // 报越界异常产生了越界异常的对象
        //new ArrayIndexOutOfBoundsException("5");
        //System.out.println(arr[5]);
        arr = null;
        System.out.println(arr[1]);
        System.out.println(10 / 0);

    }catch(ArrayIndexOutOfBoundsException e){
        System.out.println("你越界了");
    }catch (NullPointerException e) {
            System.out.println("你空指针了");
        }catch (ArithmeticException e) {
            System.out.println("你除以0了");
        }catch (Exception e) {
            System.out.println("出错了");
        }
        System.out.println("哈哈");
    运行这段代码时发现只打印了 "你空指针了""哈哈"
    因为在匹配catch的时候 有一个被匹配上了
    其他catch就不会被匹配了
    当arr = null;
      System.out.println(arr[1]);
     执行后 出现了空指针异常 catch中匹配到了
     catch (NullPointerException e) {
            System.out.println("你空指针了");
        }
        那么其他的就不会被继续匹配了
    这里需要注意的是 最后一个catch 
    catch (Exception e) {
            System.out.println("出错了");
        }
    需要放在最后,因为Exception可以被所有异常匹配到
    如果放在最前面,那么后面的catch就没有意义了
    系统就会报红
    所以catch中 异常要从小到大
小练习
    //无限输入整数 存放到集合中 打印 输入quit停止
    //希望在输入字符串的时候 让程序也能继续运行

    public class Demo {
        public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        whilie(true){
           System.out.println("输入整数");
           String string = scanner.nextLine();
           if(string.equals(quit)){
                    //停止循环
                    break;
                }
                // 处理异常
                    try{
                        // 字符串转数字
                        int num = Integer.parseInt(string);
                        //添加到数组中
                        list.add(num);
                    } catch(Exception e){
                        System.out.println("输入错误,请重新输入");
               }
            }
            System.out.println(list);
        }
    }

finally

    final finally finalize 的 区别
    final:
        类 不能被继承
        方法 不能被重写
        变量  变量变常量
    finally 异常处理时使用的
    finalize() 是一个方法 是坐垃圾回收的时候用的 是系统自己调用的
    出现异常与否 不会影响到 finally的执行
    也就是说 finally一定会执行
    finally的作用: 一般用来敢比资源 例如:关闭流合数据库
    public static void fun() {
        try {
            System.out.println( 10 / 0);
            // 即使你直接return方法 finally也会执行 
            // 直接关闭JVM虚拟机 就不会执行finally
            return;
        } catch (Exception e) {
            System.out.println("你除以0了");
        }finally {
            System.out.println("我是finally");
        }
        System.out.println("哈哈");
    }
    这里最后打印的结果是 "你除以0了" "我是finally" "哈哈"
    从这里可以看出 就算用return结束这个方法 finally也会被打印
    class TestFinally{
        public int fun() {
            int num = 10;
            try {
                num = 20;
                System.out.println(10 / 0);
                return num;
            } catch (Exception e) {
                // 捕获异常
                num = 30;
                // 建立一个返回路径 相当于一个容器
                // 容器中保存的是 要返回的值
                // 不会马上return 会看一下 有没有 finally
                // 有finally就执行 但是不会更改已经在返回路径中的值
                // 等finally执行完了 再完全return
                return num;
            }finally {
                num = 40;
                // finally中 只写关闭资源 写return 没有意义
                // 会把之前的返回值 都覆盖
                // return num;
            }
        }
    }
    这里打印的是 30
运行时异常 和编译时异常
    运行时异常是程序员编写的代码出错了
    编译时异常是为了这个可能发生才错误做的提前准备,也就是编写程序时报红
    public class Demo{
        public static void main(String[] args){
        //这句代码的意思是 读取该路径下的文件
        //系统不知道你这个路径有没有文件
        //需要提前询问你 如果没有这个路径的文件
        //就会报异常

        //这句代码写出来的时候发现编译时异常
        //编译时异常 是系统强制让你处理的
        //可以添加 try...catch 自己去处理
        //也可以把异常抛给上级去处理 自己就不用处理了
        //把异常抛给上级去处理就是 可以把问题抛给main函数
        //在 main函数的函数声明上添加 
        //throws + 要抛出异常的类名
            FileInputStream inputStram = new FileInputStream("s.txt");

            fun;
        }
    }

    //用try...catch 自己处理
    public static void fun(){
        try{
            FileInputStream inputStream = new FileInputStream("s.txt");
        }catch(Exception e){
            System.out.println("没有这个文件");
        }
    }
手动抛出异常
    /*
    * 创建一个人类 有name 和 age
    * 要求 人类的年龄赋值时 要在 0 到 120岁之前
    * 不用异常
    */
    public class Demo06 {
        public static void main(String[] args) throws Exception {
            Person person = new Person();
            person.setName("a");
            person.setAge(121);
            System.out.println(person);
        }
    }

    class Person{
        private String name;
        private int age;
        public Person() {
            super();
            // TODO Auto-generated constructor stub
        }
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        // throws关键词 在 方法的声明上 标识这个方法可能会抛出异常
        // 谁调用这个方法 这个异常就被抛给谁
        public void setAge(int age) throws Exception {
            //需要在这个范围内 才可以给age赋值
            if (age <= 120 && age >= 0) {
                this.age = age;
            }else {
                // 手动抛出一个异常
                 //throw 后面跟的是 抛出的异常对象

                Exception e = new  Exception("年龄超出范围");
                throw e;
                throw new Exception("年龄超出范围");


            }
        }
        @Override
        public String toString() {
            return "[name=" + name + ", age=" + age + "]";
        }

    }
   /*
    * 
    * 创建一个人类 有name 和 age
    * 要求 人类的年龄赋值时 要在 0 到 120岁之前
    */

    public class Demo {
    public static void main(String[] args) throws Exception {
        Person person = new Person();
        person.setName("a");
        person.setAge(121);
        System.out.println(person);
    }
    class Person{
        private String name;
        private int age;
        public Person() {
            super();
            // TODO Auto-generated constructor stub
        }
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        //throws关键词 在方法的声明上 标识这个方法可能会抛出异常
        // 谁调用这个方法 这个异常就抛给谁
        public void setAge(int age) throws Exception{
            //需要在这个范围内 才可以给age赋值
            if(age <= 120 && age >= 0 ){
                this.age = age;
            }else{

                throw new AgeOutOfBoundsException("年龄超出范围")
            }
        }
        @Override
    public String toString() {
        return "[name=" + name + ", age=" + age + "]";
    }
}

//  自定义异常
//  重点: 类名 要 见名知意 并且跟系统学习
class AgeOutOfBoundsException extends Exception{
    //写出有参无参构造函数
    public AgeOutOfBoundsException() {

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

Throwable中的方法

    public static void main(String[] args) {
        Exception exception = new Exception("这里可以写错误信息");
        //获取错误信息的方法
        String message = exception.getMessage;
        //System.out.println(message);
        //toString 方法
        //有没有toString
       // System.out.println(exception.toString());

       //打印错误信息 错误的位置 异常的类名
       exception.printStackTrace();
    }
                                                                                          Day.21

http://blog.youkuaiyun.com/ssssssue

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值