Java基础 第三节 第十九

网友投稿 588 2022-05-29

异常的处理

概述

抛出异常

使用

Objects 非空判断

声明异常 throws

捕获异常 try...catch

代码展示

获取异常信息

finally 代码块

代码演示

异常注意事项

总结

概述

Java 异常处理的五个关键字: try, catch, finally, throw, throws.

抛出异常

在编写程序时, 我们必须要考虑程序出现问题的情况. 比如, 在定义方法是=时, 方法需要接受参数. 那么, 当调用方法使用接受到参数时, 首先需要先对参数数据进行合法的判断. 若数据不合法, 就应该告诉调用者, 传递合法的数据进来. 这是需要使用抛出异常的方式来告诉调用者.

在 Java 中, 提供了一个 throw 关键字, 它用来抛出一个指定的异常对象. 那么, 抛出一个异常具体如何操作呢?

创建一个异常对象, 封装一些提示信息 (信息可以自己编写)

需要将这个异常对象告知给调用正则. 怎么告知呢? 怎么将这个异常对象传递到调用者处呢? 通过关键字 throw 就可以完成. throw 异常对象.

使用

throws 用在方法内, 用来抛出一个异常对象, 将这个异常对象传递到调用者处, 并结束当前方法的执行.

使用格式:

throw new 异常类名(参数);

1

例如:

throw new NullPointerException("要访问的arr数组不存在"); throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");

1

2

学习完抛出异常的格式后, 我们通过下面程序演示下 throw 的使用. 代码如下:

public class Test { public static void main(String[] args) { // 创建一个数组 int[] array = {1, 2, 3, 4, 5, 6}; // 根据索引找到对应的元素 int index = 6; int element = getElement(array, index); } /** * @param array 传入的int数组 * @param index 需要查找的index * @return 返回指定索引的值 */ public static int getElement(int[] array, int index) { // 判断是否越界 if (index < 0 || index > array.length - 1) { /* 判断条件如果满足, 方执行完throw抛出异常对象后, 方法已经无法继续运算 这是就会结束当前方法的执行, 并将异常告知给调用者. 这时就需要通过异常来解决 */ throw new ArrayIndexOutOfBoundsException("小哥哥, 索引越界了~~"); } int element = array[index]; return element; } } 调试输出: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 小哥哥, 索引越界了~~ at Test41.getElement(Test41.java:22) at Test41.main(Test41.java:7)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Java基础 第三节 第十九课

20

21

22

23

24

25

26

27

28

29

30

31

32

注意:

如果产生了问题, 我们就会 throw 将问题描述类即异常进行抛出, 也就是将问题返回给该方法的调用者

那么对于调用者来说, 该怎么处理呢?

一种是进行捕获处理, 另一种就是继续讲问题声明出去, 使用 throws 声明处理出去, 使用 throws 声明处理

Objects 非空判断

还记得我们学习过一个类 Objects 吗, 曾经提到过它由一些静态的实用方法组成, 这些方法是 null-save (空指针安全的) 或 null-tolerant (容忍空指针的). 那么在它的源码中, 对对象为 null 的值进行了抛出异常操作.

public static T requireNoNull(T obj): 查看指定引用对象不是 null.

查看源码发现这里对为 null 的进行了抛出异常操作:

public static T requireNonNull(T obj){ if (obj == null){ throw new NullPointerException(); } return obj; }

1

2

3

4

5

6

声明异常 throws

声明异常: 将问题标识出来, 报告给调用者. 如果方法内通过 throw 抛出了编译时异常, 而没有捕获处理 (稍后讲解该方式). 那么必须通过 throws 进行声明, 让调用者去处理.

关键字 throws 运用于方法声明之上, 同于表示放弃方法不处理异常, 而是提醒该方法的调用者来处理异常. (抛出异常)

声明异常格式:

修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }

1

声明异常的代码演示:

import java.io.FileNotFoundException; public class Test { public static void main(String[] args) throws FileNotFoundException { read("a.txt"); } // 如果定义功能有时间发生需要报告给调用者. 可以通过在方法上面throws关键字进行声明 public static void read(String path) throws FileNotFoundException { if(!path.equals("a.txt")){ // 如果不是a.txt 这个文件 // 我假设如果a.txt认为该文件不存在是一个错误也就是异常throw throw new FileNotFoundException("文件不存在"); } } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

捕获异常 try…catch

如果异常出现的话, 会立刻终止程序, 所以我们得处理异常:

该方法不处理, 而是声明抛出, 有该方法调用者来处理 (throws)

在方法中使用 try-catch 的语句块来处理异常.

try-catch 的方式就是捕获异常: Java 中对异常有针对性的语句进行捕获, 可以对出现的异常进行制定方式的处理.

捕获异常语法如下:

try{ 编写可能会出现异常的代码 }catch(异常类型 e){ 处理异常的代码 //记录日志/打印异常信息/继续抛出异常 }

1

2

3

4

5

6

try: 该代码块中编写可能产生异常的代码.

catch: 用来进行某种异常的捕获, 实现对捕获到的异常进行处理.

代码展示

import java.io.FileNotFoundException; public class Test44 { public static void main(String[] args) { try { read("a.txt"); } catch (FileNotFoundException e) { System.out.println(e); } System.out.println("over"); } // 如果定义功能有时间发生需要报告给调用者. 可以通过在方法上面throws关键字进行声明 public static void read(String path) throws FileNotFoundException { if (!path.equals("a.txt")) { // 如果不是a.txt 这个文件 // 我假设如果a.txt认为该文件不存在是一个错误也就是异常throw throw new FileNotFoundException("文件不存在"); } } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

注: try 和 catch 都不能单独使用, 必须连用.

获取异常信息

如何获取异常信息?

Throwable 类中定义了一些查看方法:

public String getMessage(): 获取异常的描述信息, 原因 (提示给用户的时候, 就提示错误原因)

public String toString(): 获取异常的类型和异常描述信息 (不用)

public void printStackTrace(): 打印异常的跟踪栈的信息并输出到控制台

注: 包含了异常的类型, 异常的原因, 还包括异常出现的wiz, 在开发和调试阶段, 都得使用printStackTrace

finally 代码块

finally: 有一些特定的代码无论异常是否发生, 都需要执行. 另外, 因为异常会引发程序跳转, 导致有些语句执行不到. 而 finally 就是解决这个问题的, 在 finally 代码块中存放的代码都是一定会被执行的.

什么时候的代码必须最终执行?

当我们在 try 语句块中打开了一些物理资源 (磁盘文件/网络连接/数据库连接等). 我们都得在使用完之后, 最终关闭打开的资源.

比如我们之后学习的 IO 流中, 当打开了一个关联的文件的资源, 最后程序不管结果如何, 都需要把这个资源关闭掉.

代码演示

import java.io.FileNotFoundException; public class Test45 { public static void main(String[] args) { try { read("a.txt"); } catch (FileNotFoundException e) { //抓取到的是编译期异常, 抛出去的是运行期 throw new RuntimeException(e); } finally { System.out.println("不管程序怎样, 这里都将会被执行!"); } System.out.println("over"); } /* * * 我们当前的这个方法中有异常有编译期异常 */ public static void read(String path) throws FileNotFoundException { if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 // 我假设 如果不是a.txt, 认为该文件不存在, 是一个错误也就是异常, throw throw new FileNotFoundException("文件不存在"); } } }

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

注: 当只有在 try 或者 catch 中调用退出 JVM 的相关方法, 此时 finally 才不会执行, 否则finally 永远会执行.

异常注意事项

多个异常使用捕获又该如何处理呢?

多个异常分别处理

多个异常一次捕获, 多次处理

多个异常一次捕获一次处理

一般我们是使用一次捕获多次处理的方式, 格式如下:

try{ 编写可能会出现异常的代码 }catch(异常类型A e){ 当try中出现A类型异常,就用该catch来捕获. 处理异常的代码 //记录日志/打印异常信息/继续抛出异常 }catch(异常类型B e){ 当try中出现B类型异常,就用该catch来捕获. 处理异常的代码 //记录日志/打印异常信息/继续抛出异常 }

1

2

3

4

5

6

7

8

9

注: 这种异常处理方式, 要求多个 catch 中的异常不能相同, 并且若 catch 中的多个异常之间有子类和父类异常的关系, 那么子类异常要求在上面的 catch 处理, 鱼类异常在下面的 catch 处理.

总结

运行时异常被抛出可以不处理, 即不捕获也不声明抛出

如果 finally 有 return 语句, 永远返回 finally 中的结果, 避免该情况

如果父类抛出了多个异常, 子类重写父类方法时, 抛出和父类相同的异常或者是父类的子类或者不抛出异常

父类方法没有抛出异常, 子类重写父类方法时也不可抛出异常, 此时子类产生该异常, 只能捕获, 不能声明抛出

Java

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:谈谈 C++ 单例模式
下一篇:每天一个IDA小技巧(二):基本代码转换
相关文章