【Java】编译时异常和运行时异常

编译时异常和运行时异常,它们两个有什么区别呢?我们先写个代码,再画个图,就恍然大悟了。

一、代码

1)编译时异常

//编译时异常
String time = "2030年1月1日";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
Date date = sdf.parse(time);
System.out.println(date);

parse() 解析方法会有一条红色波浪线

image-20240501112253847

想要让代码成功运行,我们需要用鼠标点一下方法,alt + 回车 ,然后选择第一个,这才可以。

image-20240501112416594

我们是这样的呢?其实就是因为 parse() 底层有 ParseException,这个异常就是编译时期异常。

编译时期异常在编译阶段,必须要手动处理,否则代码报错。


2)运行时异常

在之前我们遇到的索引越界,就是一个标准的运行时期异常。

int[] arr = {1,2,3,4,5};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException

运行时异常在编译阶段是不会出现问题的,只有当真正运行的时候才会出现问题。

image-20240501112744570

运行时异常在编译阶段是不需要处理的,是代码运行时出现的异常。


二、画图

一开始我们写的是Java文件,如果我想要运行代码,首先通过 javac 进行编译,编译成字节码文件,这个阶段叫做编译阶段。

在这个阶段中要处理的异常叫做:编译时异常。

例如我们刚刚书写的 ParseException(日期解析日常),你不处理,代码就报错,这就是它最大的特点。


编译完后,需要通过 java命令 去运行代码,那么在运行时出现的异常就是:运行时异常。

它是 RuntimeException本身及其子类,运行时异常它在编译阶段不需要处理,而是代码运行时出现的异常。

例如 ArrayIndexOutOfBoundsException(数组索引越界异常),就算代码真的有问题了真的越界了,编译阶段也不会出现问题,只有代码运行的时候才会出现的异常。

image-20240501113647757

三、扩展

你觉得Java为什么这么设计呢?为什么要分编译时异常运行时异常呢?为什么不能把所有的异常都归为一类呢?

其实是有原因的,在编译的时候Java是不会运行代码的,只会检查语法是否错误,或者做一些性能的优化。

例如定义变量的类型错了,这个就是语法错误,在编译的时候Java会检查。

image-20240501113805883

再比如说字符串拼接的优化机制:在编译之后,等号的右边就变成了最终的结果 "abc"

image-20240501113931814

但是如果遇到索引越界,在编译的时候它是不知道的。

例如以下代码,先获取一个随机数,再根据随机数创建相应长度的数组,获取 10索引 上的元素,此时只有当代码真正运行了,才能确认代码的长度,才能确定索引是否超出范围。

因此像这种运行时发生的异常,是不能放到编译时的,只能在运行的时候才能确定它是否真的超出范围。

因此,索引越界异常是属于运行时发生的异常。


那这样问题又来了,那为什么不把所有的异常都放在下面的运行时呢?

image-20240501114316768

因为编译型异常更多的在于提醒程序员检查本地信息,告诉程序员:如果有问题就会出现异常。

例如:日期解析日常,parse() 方法底层会涉及到本地时区的相关信息。

再比如说,后面我们会用 IO 去读取本地文件的数据,而这个文件 a.txt 也是在本地操作系统中的,因此在这个代码中,它也会有编译时异常,用来提醒程序员检查本地的 a.txt 是否真的存在。

而下面运行时期异常,它的核心不在于提醒,它就是由于代码出错而导致程序出现的问题。


四、这两种异常在开发中都包含哪些呢?

我们可以打开一下 API帮助文档 看一下。

搜索 Exception ,这里显示的所有的都是异常,其中 RuntimeException 就是运行时异常。

而除了 RuntimeException 以外,所有的都是编译时异常。

image-20240501115041469

点进 RuntimeException 看一下,可以发现它也有很多子类。

RuntimeException 所有的子类都是运行时异常,都是由于我们在代码中参数写错了而出现的异常。

image-20240501115418322

IndexOutOfBoundsException 为例,点进去看一下,可以发现它下面还有两个子类

image-20240501115506731

五、总结

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

编译时异常,在语法中,它是直接继承 Exception:除了 RuntimeException和它的子类,其他都是编译时异常。编译阶段需要进行处理,作用在于提醒程序员。

运行时异常:RuntimeException本身和所有子类 都是运行时异常。在编译阶段是不会报错的,是程序运行时出现的异常。

这种异常一般是由于程序员代码写错了,参数传递错误代理的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值