专业的JAVA编程教程与资源

网站首页 > java教程 正文

SE为什么需要异常处理机制?Java异常详解18张图万字带你搞懂异常

temp10 2024-09-16 05:19:30 java教程 13 ℃ 0 评论

文章目录

1 异常引入

SE为什么需要异常处理机制?Java异常详解18张图万字带你搞懂异常

2 异常简介

2.1 异常的概念

2.2 常见异常体系图

3 常见运行时异常举例

3.1 NullPointerException

3.2 ArrayIndexOutOfBoundsException

3.3 ClassCastException

3.4 NumberFormatException

4 异常处理

4.1 try-catch-finally 异常处理

4.2 try - catch练习题(坑)

4.2.1 阅读程序

4.2.2 输入校验

4.3 throws 异常处理

4.4 自定义异常

4.4.1 自定义异常实例

4.5 throw 和 throws 的区别

5 编程练习

写在最后

1 异常引入

不知道初学Java 时,大家是不是和博主一样一脸懵:“这异常到底是个什么东东,有什么用嘞?” 今天,咱们就专门来展开讲讲异常。

还是那个教科书里面的标准例子,来看一下吧:

在例子中,我们将 0 作为除数进行运算,运行结果如下:


程序控制台好像出现了不得了的东西!细细一看,原来是告诉我们出现了算术异常。不过只要再细心看一下代码,你就会发现:程序并没有执行完成,因为控制台并没有输出“程序运行结束标记”这句话!而是在计算 res 的时候,就中断了。 这就导致了一个很严重的问题:在我们实际开发中,一个完整的项目,文件可能都多达上千个,难道可以因为这样的小错误就直接崩溃,停止运行吗?

答案是否定的,因此, 我们需要使用异常处理机制,来提升项目的健壮性!

在idea编译器中,我们可以先选中代码块,然后使用快捷键 ctrl + alt + t 在弹出的二级菜单中,一键添加 try - catch ,(偷懒小技巧增加了~~~)
来看一下添加异常机制后,程序的运行情况吧!
代码如下:

运行结果:


虽然运行结果同样抛出了异常信息,但是,程序并没有因此而中止!而是继续向后执行,结束标记输出就是最好的证明~
怎么样?现在是不是就对异常有兴趣啦!来,进入正题,我们慢慢聊~


2 异常简介

2.1 异常的概念

在 Java 中,异常即为程序执行过程中发生的不正常情况。 但是需要注意的是,程序员在编码过程中的逻辑与语法错误不属于异常的范畴!

程序执行过程中所发生的异常可以分为如下两大类:

1?? Error: Java 虚拟机无法解决的严重问题。如: JVM系统内部错误、资源耗尽等。举例:栈溢出(StackOverflowError)

2?? Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。分为两大类:

运行时异常: 又叫非受检异常,即程序运行时,发生的异常;

编译时异常: 又叫受检异常,即编程时,编译器检查出的异常。

图示如下:

助记:

编译时异常: 编译器检查出来的异常,必须处理,不然运行不了;

运行时异常: 编译器没有检查出来,程序可以跑,可以 选择性处理。

2.2 常见异常体系图

Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。Java异常体系结构呈树状,常见异常的层次结构图如图所示:

Throwable 实现了 Serializable 接口。向下分为 Error Exception。而 Exception 我们可以通过异常处理机制来解决。我们着重处理 RuntimeException运行时异常,其常见的子类如下,上面的图可能看不清,我们来放大看:

3 常见运行时异常举例

3.1 NullPointerException

空指针异常,当应用程序在需要对象的地方使用null时,抛出该异常。

示例代码:

public class NullPointerException {

public static void main(String[] args) {

String s = null;

System.out.println(s.length());

}

}

结果:

Exception in thread “main” java.lang.NullPointerException: Cannot invoke “String.length()” because “s” is null

at exception.NullPointerException.main(NullPointerException.java:10)

3.2 ArrayIndexOutOfBoundsException

数组下标越界异常。 用非法索引访问数组时抛出该异常,即数组越界。

示例代码:

public class ArrayIndexOutOfBoundsException {

public static void main(String[] args) {

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

System.out.println(arr[3]); // 越界

}

}

1

2

3

4

5

6

结果:

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3

at exception.ArrayIndexOutOfBoundsException.main(ArrayIndexOutOfBoundsException.java:10)

3.3 ClassCastException

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

示例代码:

public class ClassCastException {

public static void main(String[] args) {

Animal dog = new Dog();

Dog d = (Dog)dog; // 向下转型

Cat c = (Cat)dog; // 该句错误!!!!

}

}

class Animal{}

class Dog extends Animal{}

class Cat extends Animal{}

1

2

3

4

5

6

7

8

9

10

结果:

Exception in thread “main” java.lang.ClassCastException: class exception.Dog cannot be cast to class exception.Cat (exception.Dog and exception.Cat are in unnamed module of loader ‘app’)

at exception.ClassCastException.main(ClassCastException.java:11)

3.4 NumberFormatException

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

示例代码:

public class NumberFormatException {

public static void main(String[] args) {

int num = Integer.parseInt("123.456"); // 转不了

}

}

1

2

3

4

5

结果:

Exception in thread “main” java.lang.NumberFormatException: For input string: “123.456”

at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)

at java.base/java.lang.Integer.parseInt(Integer.java:652)

at java.base/java.lang.Integer.parseInt(Integer.java:770)

at exception.NumberFormatException.main(NumberFormatException.java:9)

4 异常处理

异常处理即当异常发生时,对异常处理的方式。 主要有两种处理方式:

try-catch-finally:程序员在代码中自行处理,捕获异常;

throws:将异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM。示意图如下:

main方法如果没有进行 try catch,默认会进行 throws。

4.1 try-catch-finally 异常处理

Java 提供 try 和 catch 块来处理异常。try 块用于包含可能出错的代码,catch 块用于处理 try 块发生的异常。finally 块可选择性添加,用于执行始终需要执行的代码。

? 基本语法:

try{

// 可能发生异常的代码

// 将异常生成对应的异常对象,传递给 catch 块

}catch(异常){

// 对异常的处理

}finally{

// 不管 try 是否有异常,始终都要执行 finally 块的代码

// 通常将需要释放资源的代码放在 finally

}

1

2

3

4

5

6

7

8

9

使用细节:

1?? 如果异常发生了,则异常后面的代码不会执行,直接进入到 catch 块。

如果异常没有发生,则顺序执行 try 代码块,不会进入 catch 块。


如果 try 代码块有多个异常,可以使用多个 catch 分别捕获并进行相应的处理。 但是要求 子类必须在父类前面! 值得注意的是,异常捕获的时候,当捕获到第一个,后面的将不再捕获。


允许使用 try - finally ,但是这种做法相当于没有捕获异常,finally
相当于进行了善后处理, 即 程序还是会因为异常中断,但是会执行该代码块中的代码后再中断(垂死挣扎)


4.2 try - catch练习题(坑)

4.2.1 阅读程序

请阅读下面代码,猜猜输出结果:

public class Exception01 {

public static int method(){

int i = 1;

try {

i++;

String[] name = new String[3];

if(name[1].equals("ABC")){ // 发生了空指针异常

System.out.println("ABC");

}

}catch (NullPointerException e){

return ++i;

}finally {

++i;

System.out.println("i = " + i);

}

return 0;

}

public static void main(String[] args) {

System.out.println(method());

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

结果:

i = 4

3

解析:在 if 语句中发生了空指针异常,try 块其余代码不执行。执行 catch 块代码,此时应该 return 3。但是由于 finally 块一定要被执行,因此,程序会先将 return 的 i 值暂时存储起来,去执行 finally 块的代码。所以先输出 i = 4 后返回3.

4.2.2 输入校验

题目要求:

请你编写一段程序,用于判断用户的输入:如果输入不是整数,就提示错误信息,直到输入正确为止。

思路分析:

创建 Scanner 对象;

使用循环去接收一个输入;

将该输入尝试转换成 int;

如果转换时发生异常,说明输入有误,不能转换;

如果没有抛出异常,则输入正确,提示即可。

参考代码:

public class TryCatch {

public static void method() {

Scanner scanner = new Scanner(System.in);

int num = 0;

while (true) {

System.out.println("请输入一个整数: ");

try {

num = Integer.parseInt(scanner.next()); // 有可能抛出异常

break; // 没有抛出则退出循环

} catch (NumberFormatException e) {

System.out.println("你输入的不是整数, 请重新输入!");

}

}

System.out.println("输入正确!");

}

public static void main(String[] args) {

method();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

实验结果:

4.3 throws 异常处理

基本介绍:

如果一个方法可能生成某种异常,但是 并不确定如何处理这些异常,则该方法应显式地声明抛出异常 ,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。在方法声明中抛出异常的列表,throws 后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

? 基本语法:

方法名 throws 异常类1, 异常类2......{

// 方法体

}

1

2

3

使用细节:

1?? 对于运行时异常,程序如果没有处理,默认就是 throws 的方式处理;

2?? 子类重写父类的方法时,对抛出异常有一条规定:子类重写的方法,所抛出的异常类型要么与父类抛出的异常一致,要么为父类抛出的异常类型的子类型; 演示如下:

4.4 自定义异常

当程序出现了某些错误,但该错误信息并没有在 Throwable 子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。

自定义异常的步骤:

1.定义类:自定义异常类名,继承 Exception 或者 RuntimeException;

2. 如果继承了 Exception,属于编译异常;

3.如果继承了 RuntimeException,属于运行异常。

4.4.1 自定义异常实例

来看一个需求:

当接收 Person 对象年龄时,要求范围在 18~120 之间,否则抛出自定义异常,并给出提示信息。(要求继承 RuntimeException)

? 参考代码:

public class Main {

public static void main(String[] args) {

Person person = new Person(125); // 设置年龄125 出现了异常

}

}

class Person{

private int age;

public Person(int age){

this.age = age;

ageException();

}

// 判断异常

public void ageException(){

if(!(age >= 18 && age <= 120)){

throw new AgeException("年龄需要在18 ~ 120之间");

}

System.out.println("范围正常");

}

}

// 自定义异常

class AgeException extends RuntimeException{

public AgeException(String message){

super(message);

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

结果:

4.5 throw 和 throws 的区别

区别一览表:


5 编程练习

题目描述(题目摘自 bilibili 韩顺平 Java 课程 P456):

编写程序接收两个参数(整数),计算两数相除。要求使用方法 cal(int num1, int num2)。对于数据格式不正确(NumberformatException)、缺少命令行参数(ArrayIndexOutOfBoundsException)、除0进行异常处理(ArithmeticException)。

参考代码:

public class Main {

public static void main(String[] args) {

// 先检验输入参数的个数

try {

if(args.length != 2){

throw new ArrayIndexOutOfBoundsException("参数个数不对");

}

// 把接收到的参数转成整数

int n1 = Integer.parseInt(args[0]);

int n2 = Integer.parseInt(args[1]);

double res = cal(n1, n2); // 可能算数异常

} catch (ArrayIndexOutOfBoundsException e) {

System.out.println(e.getMessage());

} catch (NumberFormatException e){

System.out.println("参数格式不正确");

} catch (ArithmeticException e) {

System.out.println("算术异常,0不能做除数");

}

}

// 编写方法,计算

public static double cal(int n1, int n2){

return n1/n2;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

输入(配置如下图,注意用空格分隔):

结果:

算术异常,0不能做除数

总结了很多有关于java面试的资料,希望能够帮助正在学习java的小伙伴。由于资料过多不便发表文章,创作不易,望小伙伴们能够给我一些动力继续创建更好的java类学习资料文章,

请多多支持和关注小作,别忘了点赞+评论+转发。右上角私信我回复【03】即可领取免费学习资料谢谢啦!




































原文出处:https://blog.csdn.net/m0_60353039/article/details/124697705?spm=1001.2100.3001.7377&utm_medium=distribute.pc_feed_blog_category.none-task-blog-classify_tag-2-124697705-null-null.nonecase&depth_1-utm_source=distribute.pc_feed_blog_category.none-task-blog-classify_tag-2-124697705-null-null.nonecase

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表