java中的异常(带你全面了解异常)

本文详细介绍了Java中的异常处理机制,包括try-catch块的使用,多异常捕获,finally的善后处理,以及如何声明和抛出异常。同时探讨了资源管理和错误类型的重要性,以及自定义异常的实践和注意事项。
摘要由CSDN通过智能技术生成

System.out.println(“before”);

System.out.println(arr[100]);

//因为此时上面的代码发生了异常,所以此时下面的代码是不会被执行的。

System.out.println(“after”);

} catch (ArithmeticException e) {

e.printStackTrace();

System.out.println(“此段代码不会执行”);

} catch (ArrayIndexOutOfBoundsException e) {

e.printStackTrace();

System.out.println(“捕获了数组越界异常”);

}

System.out.println(“after try catch”);

}

}

//输出结果为

before

捕获了数组越界异常

after try catch

java.lang.ArrayIndexOutOfBoundsException: 100 at yichang.main(yichang.java:11)

假如此时try中的代码发生的是数组下标越界异常,但是第一个catch中捕获的却是算术异常,那么这个catch中的代码是不会被执行的,第二个catch捕获的是数组下标越界异常,那么就会正常执行里面的代码,最后再执行System.out.println(“after try catch”);这条语句.

方法2:

除了可以像上述那样捕获多个异常以外,我们还可以通过|这个符号来捕获多个异常

如果多个异常的处理方式是完全相同****,**** 也可以写成这样:

catch (ArrayIndexOutOfBoundsException | NullPointerException e) {

}

public class yichang {

public static void main(String[] args) {

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

//catch代码块可以捕获多个异常

try {

System.out.println(“before”);

System.out.println(arr[100]);

//因为此时上面的代码发生了异常,所以此时下面的代码是不会被执行的。

System.out.println(“after”);

} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {

System.out.println(“此段代码不会执行”);

e.printStackTrace();

}

System.out.println(“after try catch”);

}

}

//输出结果为

before

此段代码不会执行

java.lang.ArrayIndexOutOfBoundsException: 100 at yichang.main(yichang.java:11)

after try catch

代码4 也可以用一个 catch 捕获所有异常(不推荐****)****

public class yichang {

public static void main(String[] args) {

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

//也可以用一个 catch 捕获所有异常(不推荐)

try {

System.out.println(“before”);

System.out.println(arr[100]);

//因为此时上面的代码发生了异常,所以此时下面的代码是不会被执行的。

System.out.println(“after”);

//由于 Exception 类是所有异常类的父类. 因此可以用这个类型表示捕捉所有异常.

} catch (Exception e) {

e.printStackTrace();

System.out.println(“此段代码会执行”);

}

}

}

//输出结果

before

java.lang.ArrayIndexOutOfBoundsException: 100 at yichang.main(yichang.java:11)

此段代码会执行

由于 Exception 类是所有异常类的父类. 因此可以用这个类型表示捕捉所有异常.

代码5 finally

finally表示最后的善后工作, 例如释放资源.

scanner对象此时表示的是一种资源,资源最终要被释放

public class yichang {

public static void main(String[] args) {

//scanner中的close方法

Scanner scanner = new Scanner(System.in);

try {

int a = scanner.nextInt();

System.out.println(10 / a);

} catch (ArithmeticException e) {

e.printStackTrace();

} finally {

scanner.close();

System.out.println(“不管是否发生异常,finally块都会永远被执行”);

}

}

}

//输出结果

java.lang.ArithmeticException: / by zero at yichang.main(yichang.java:13)

不管是否发生异常,finally块都会永远被执行

注意:无论是否找到匹配的异常类型****, finally**** 中的代码都会被执行到****(在该方法结束之前执行). 来看如下代码****

public class yichang {

public static void main(String[] args) {

int a=0;

try {

int ret=10/a;

}catch (ArrayIndexOutOfBoundsException e){

}finally {

System.out.println(“hhhh”);

}

}

}

输出结果为:

hhhh

Exception in thread “main” java.lang.ArithmeticException: / by zero

at yichang.main(yichang.java:9)

可以看到,此时我们并没有在catch中找到匹配的异常类型,所以catch中的语句并不会执行,但是finally中的语句是无论是否找到匹配的异常类型********, finally 中的代码都会被执行到,所以最终先输出hhh,再抛出算术异常.

代码6 使用try负责回收资源

刚才在代码5中,我们使用finally来回收资源,现在还有一种等价写法****,**** Scanner 对象在 try ( ) 中创建****,**** 就能保证在 try 执行完毕后自动调用 Scanner********的 close 方法****.最终在finally中也不再需要去调用close方法.****

public class yichang {

public static void main(String[] args) {

try(Scanner scanner = new Scanner(System.in)) {

int a = scanner.nextInt();

System.out.println(10 / a);

} catch (ArithmeticException e) {

e.printStackTrace();

} finally {

System.out.println(“不管是否发生异常,finally块都会永远被执行”);

}

}

}

//输出结果

0

java.lang.ArithmeticException: / by zero at yichang.main(yichang.java:11)

不管是否发生异常,finally块都会永远被执行

代码7 建议finally中不要使用return语句

public class yichang {

public static int func() {

try {

int a = 10;

int ret = 10 / a;

return ret;

} catch (Exception e) {

e.printStackTrace();

} finally {

return 10;

}

}

public static void main(String[] args) {

System.out.println(func());

}

}

//输出结果

10

原因是当我们调用func函数其实最想获得的是10/a的返回值,但是当我们在func函数中使用了finally之后,func函数的返回值变为了finally函数中return出来的值,不是我们想要的结果,所以最终输出结果不是3,而是10.所以我们并不建议在finally中使用return语句.

代码8 如果本方法中没有合适的处理异常的方式****,**** 就会沿着调用栈向上传递

在下面代码中,首先func方法并没有处理数组下标越界异常,所以此时会沿着栈向上传递到main方法,最终在main方法中找到了try catch来处理数组下标越界这个异常.

public class yichang {

public static void func3() {

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

System.out.println(arr[100]);

}

public static void main(String[] args) {

try {

func3();

} catch (ArrayIndexOutOfBoundsException e) {

e.printStackTrace();

}

System.out.println(“after try catch”);

}

}

//输出结果

java.lang.ArrayIndexOutOfBoundsException: 100

at yichang.func3(yichang.java:8)

at yichang.main(yichang.java:13)

after try catch

代码示例****9 如果向上一直传递都没有合适的方法处理异常, 最终就会交给 JVM 处理, 程序就会异常终止(和我们最开始未使用 try catch 时是一样的)

public class yichang {

public static void func() {

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

System.out.println(arr[100]);

}

public static void main(String[] args) {

func();

System.out.println(“hhh”);

}

}

输出结果为

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 100

at yichang.func(yichang.java:8)

at yichang.main(yichang.java:13)

可以看到****,**** 程序已经异常终止了****,**** 没有执行到 System.out.println(“after try catch”)********; 这一行****.****

总结

异常处理流程

1:程序先执行 try 中的代码.

2:如果 try 中的代码出现异常****,**** 就会结束 try 中的代码****,**** 看和 catch 中的异常类型是否匹配****.**** 如果找到匹配的异常类型****,**** 就会执行 catch 中的代码.

3:如果没有找到匹配的异常类型****,**** 就会将异常向上传递到上层调用者****.****

4:无论是否找到匹配的异常类型****, finally**** 中的代码都会被执行到****(在该方法结束之前执行).**** 如果上层调用者也没有处理的了异常****,**** 就继续向上传递****.****

5:一直到 main 方法也没有合适的代码处理异常****,**** 就会交给 JVM 来进行处理****,**** 此时程序就会异常终止****.****

3.3声明和抛出异常


声明异常:使用throws关键字

抛出异常:使用throw关键字

一般声明异常和抛出异常都是搭配使用的,一个方法执行体中抛出了异常后,要在这个方法的后面声明抛出了哪些异常,这样是为了告诉方法的调用者这个方法声明了哪些异常,好让方法的调用者根据声明的不同异常来做出相应的处理操作,下面来看代码:

public class yichang {

public static void func(int y) throws ArithmeticException,ArrayIndexOutOfBoundsException {

if(y==0){

throw new ArithmeticException();

}

System.out.println(10/y);

}

public static void main(String[] args) {

try {

func(0);

} catch (ArithmeticException|ArrayIndexOutOfBoundsException e) {

System.out.println(“jj”);

} finally {

System.out.println(“hh”);

}

}

}

3.4异常小练习


第1题(单选题)

题目名称

关于Java的异常处理机制的叙述哪些正确?

题目内容

A.如果程序发生错误及捕捉到异常情况了,才会执行finally部分

B.其他选项都不正确

C.当try区段的程序发生异常且被catch捕捉到时,才会执行catch区段的程序

D.catch部分捕捉到异常情况时,才会执行finally部分

正确答案:C

第2题(单选题)

题目名称

有关下述Java代码描述正确的选项是____。

public class TestClass {

private static void testMethod() {

System.out.println(“testMethod”);

}

public static void main(String[] args) {

((TestClass)null).testMethod();

}

}

题目内容

A.编译不通过

B.编译通过,运行异常,报NullPointerException

C.编译通过,运行异常,报IllegalArgumentException

D.编译通过,运行异常,报NoSuchMethodException

E.编译通过,运行异常,报Exception

F.运行正常,输出testMethod

正确答案:F

解析:因为testMethod方法为静态方法,是不依赖于对象的,所以最终经过类型强转后是可以正常输出的.

第3题(单选题)

题目名称

下列程序的运行结果

public void getCustomerInfo() {

try {

// do something that may cause an Exception

} catch (java.io.FileNotFoundException ex) {

System.out.print(“FileNotFoundException!”);

} catch (java.io.IOException ex) {

System.out.print(“IOException!”);

} catch (java.lang.Exception ex) {

System.out.print(“Exception!”);

}

}

题目内容

A.IOException!

B.IOException!Exception!

C.FileNotFoundException!IOException!

D.FileNotFoundException!IOException!Exception!

正确答案:A

解析:从题中我们可以看到Exception这个异常是IOException这个异常的父类,而IOException是FileNotFoundException这个异常的父类,所以从整个代码来看的话,从上到下构成了子类到父类这样一个顺序,当try中假设抛出了FileNotFoundException这个异常的话,最终只会抛出对应 catch (java.io.FileNotFoundException ex)中的语句,并不会将catch (java.io.IOException ex)和 catch (java.lang.Exception ex)这两个catch中的语句抛出。

反例:假设此时我们变化catch的顺序,那么最终会发生什么呢?来看代码吧:

public void getCustomerInfo() {

try {

// do something that may cause an Exception

} catch (java.lang.Exception ex) {

System.out.print(“Exception!”);

} catch (java.io.IOException ex) {

System.out.print(“IOException!”);

} catch (java.io.FileNotFoundException ex) {

System.out.print(“FileNotFoundException!”);

}

}

当我们变化顺序后,当try中假设抛出了FileNotFoundException这个异常的话,最终只会抛出对应 catch (java.lang.Exception ex)中的语句,并不会将catch (java.io.IOException ex)和 catch (java.lang.FileNotFoundException ex)这两个catch中的语句抛出。

原因是Exception是FileNotFoundException的父类,父类已经捕捉到这个异常了,下面的catch语句当然不用再就继续捕捉了,且不管顺序如何,构成子父类关系的catch语句也只有一个会被执行

总结:以后捕捉异常的时候,从上往下,一定注意顺序,如果最上面是父类,那么下面的捕捉语句都不会被执行,所以应该先写子类的catch语句,再写父类的catch语句。

第5题(单选题)

题目名称

下面有关JAVA异常类的描述,说法错误的是?

题目内容

A. 异常的继承结构:基类为Throwable,Error和Exception继承Throwable,RuntimeException和IOException等继承Exception

B.非RuntimeException一般是外部错误(非Error),其必须被 try{}catch语句块所捕获

C. Error类体系描述了Java运行系统中的内部错误以及资源耗尽的情形,Error不需要捕捉

D.RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等,必须被 try{}catch语句块所捕获

正确答案:D

解析:

A:正确

B:非RuntimeException包括了Error和编译时异常,然后又加上非Error后,就只剩下了编译时异常,编译时异常是必须被try catch捕获的

C:正确

D:运行时异常不一定非要被try catch捕获,不去捕获的话便会交给JVM去处理


4.自定义异常

=======

注意事项


1:自定义异常通常会继承自 Exception 或者 RuntimeException.

2:继承自 Exception 的异常默认受查异常(编译时异常).

3:继承自 RuntimeException 的异常默认非受查异常(运行时异常).

代码实例


代码1:手动定义异常原因

在手动抛出异常的时候,可以说明产生这个异常的原因,在异常后面的括号内写入原因即可

public class yichang {

public static void main(String[] args) {

try {

throw new ArithmeticException(“抛出算术异常”);

} catch (ArithmeticException e) {

e.printStackTrace();

}

}

}

输出结果为:

java.lang.ArithmeticException: 抛出算术异常

at yichang.main(yichang.java:14)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

给大家送一个小福利

附高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、准备面试跳槽、自身职业规划迷茫的朋友们。

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

java.lang.ArithmeticException: 抛出算术异常

at yichang.main(yichang.java:14)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-M9bM4f8v-1711784221971)]

[外链图片转存中…(img-LJu1AbZ5-1711784221972)]

[外链图片转存中…(img-YuPyC7RM-1711784221972)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

给大家送一个小福利

[外链图片转存中…(img-CfPakvsR-1711784221972)]

附高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、准备面试跳槽、自身职业规划迷茫的朋友们。

[外链图片转存中…(img-GE9YSNAV-1711784221973)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值