异常(超详细)

本文详细介绍了Java异常处理,包括异常体系、编译时异常与运行时异常的区别、异常的作用、JVM处理异常的方式、try-catch捕获异常的机制以及如何抛出异常。同时,提到了自定义异常的步骤,强调了在处理异常时要考虑各种可能的情况,确保程序的健壮性。
摘要由CSDN通过智能技术生成

异常(超详细)

一:异常体系介绍

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

误区:不是让我们以后不出异常,而是程序出了异常后,该如何处理

(2)在Java当中其实有很多很多异常,这些异常组成了异常的继承体系,最上层的时throwable,下面有两个子类Error和Exception。在Exception异常的下面还有两个分类,RuntimeException和其他异常,我们之前的ArithmeticException、ArrayIndexOutOfBoundsException都是RuntimeException的子类。

在这里插入图片描述

Error:代表的系统级别错误(属于严重问题),比如内存溢出,这就是你由于内存不足导致的错误,是属于硬件的问题,我们代码层面不需要管,也管不了。系统一旦出现问题,sun公司会把这些错误封装成Error对象。Error是给sun公司自己用的,不是给我们程序员用的。因此我们开发人员不用管它。

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

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

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

(3)小结:

1.异常是什么?

程序中可能出现的问题

2.异常体系的最上层父类是谁?异常分为几类?

父类:Exception

异常分为两类:编译时异常、运行时异常

3.编译时异常和运行时异常的区别?

编译时异常:没有继承RuntimeException的异常,直接继承于Exception。编译阶段就会错误提示。

运行时异常:RuntimeException本身和子类。编译阶段没有错误提示,运行时出现的

二:编译时异常和运行时异常

(1)看看下面这段代码

public class ExceptionTest1 {
   
    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); // parse下面会有一个红色波浪线
        System.out.println(date); // Tue Jan 01 00:00:00 CST 2030

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

一开始我们写的是Java文件,如果说我想要运行代码,首先是通过JavaC进行编译,编译成字节码文件,上面这个就叫做编译阶段,在这个阶段中要处理的异常就叫做编译时异常,比如上面的parseException日期解析异常,他就是一个编译时期异常,你不处理,代码就一直报错,这就是它最大的特点。编译完了之后,我们需要通过Java去运行代码,那么在运行的时候出现的异常就是运行时异常,它是RuntimeException本身或者是它的子类。运行时期异常在编译阶段不需要处理,是代码运行的时候出现的异常,比如刚刚的数组索引越界异常,只有代码运行的时候才会出现。

在这里插入图片描述

(2)Java为什么要这么设计?为什么要分为编译时期异常和运行时期异常?为什么不能把所有的异常都归为一类呢?

在编译的时候Java是不会运行代码的,他只会检查语法是否错误或者是做一些性能的优化。比如说定义变量类型错了,这是语法错误,在编译的时候Java会检查,再比如说字符串拼接的优化机制,在编译之后等号的右边就变成了最终的结果String s = "abc"了(原来是Stirng s = “a” + “b” + “c”),这是性能的优化。但是如果遇到索引越界,在编译的时候它是不知道的。比如下面这段代码:

int[] arr = new int[随机数];
int num = arr[10];

只有代码真正运行了,我才知道索引的长度,才能确定索引是否超出范围,像这种只能在运行的时候发生的异常,能放到编译时吗?

(3)那为什么不都放在运行时异常RuntimeException下面呢?

因为编译时期异常更多的是在于提醒程序员检查本地信息,比如日期解析异常,parse方法的底层会涉及到本地操作系统当中时区的相关信息。再比如说用IO去读取本地文件的数据,而这个文件他也是在本地操作系统当中的,用来提醒程序员去检查这个文件是不是真的存在。总而言之,编译时期异常是在于提醒程序员去检查本地信息,告诉程序员如果有问题就会出这个异常。而运行时期异常,它的核心不在于提醒,他就是由于代码出错而导致程序出现的问题。

(4)小结:

1.运行时异常和编译时异常的区别?

1)编译时异常:除了RuntimeException和它的子类,其他类都是编译时异常。编译阶段需要进行处理,作用在于提醒程序员检查本地信息。

2)运行时异常:RuntimeException本身和所有子类,都是运行时异常。编译阶段不报错,是程序运行时出现的。一般是由于参数传递错误带来的问题。

三:异常在代码中的两个作用

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

public class ExceptionDemo2 {
   
    public static void main(String[] args) {
   
        Student[] arr = new Student[3]; // null null null
        String name = arr[0].getName();
        System.out.println(name); // NullPointerException
    }
}
class Student {
   
    private String name;
    private int age;
    // get set等方法省略...
}

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

public class ExceptionDemo3 {
   
    public static void main(String[] args) {
   
        Student2 student2 = new Student2();
        student2.setAge(99); //年龄超出范围
        System.out.println(student2);
    }
}

class Student2 {
   
    private String name;
    private int age;
    public void setAge(int age) {
   
        if (age < 18 || age > 40) {
   
            System.out.println("年龄超出范围");
        } else {
   
            this.age = age;
        }
    }
}

在上面这个创建学生对象中,给学生对象的年龄赋值,在这个过程当中,他一共有三个角色。第一个是JavaBean的Student代码,还有main方法的调用处是调用setAge()方法的,还有第三个是控制台。在一开始是调用处调用了Student里面的代码,在上面的代码中,Student类并没有将赋值的结果告诉给调用者,而是直接打印在了控制台。这个时候站在调用者的角度去思考,他根本不知道赋值的结果。这个时候怎么办?此时就可以用异常去解决,在setAge()这个方法中,直接给调用者返回一个异常,此时调用者就知道当前的赋值情况了。得到异常之后,可以选择打印在控制台或者是自己单独处理。

public class ExceptionDemo3 {
   
    public static void main(String[] args) {
   
        Student2 student2 = new Student2();
        student2.setAge(99); //RuntimeException
        System.out.println(student2);
    }
}

class Student2 {
   
    private String name;
    private int age;
    public void setAge(int age) {
   
        if (age < 18 || age > 40) {
   
            throw new RuntimeException(); 
            // 这个时候,它的结果就不会
  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值