目录
try-catch块中存在return语句,是否还执行finally块,如果执行,说出执行顺序?
try-catch- finally块中, finally块唯一不执行的情况是什么?
生活中的异常
正常情况下,小王每日开车去上班,耗时大约30分钟
但是,由于车多、人多、路窄,异常情况很有可能发生!
程序场景
以下程序运行时会出现错误吗?
public class Test { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("请输入被除数:"); int num1 = in.nextInt(); System.out.print("请输入除数:"); int num2 = in.nextInt(); System.out.println(String.format("%d / %d = %d", num1, num2, num1/ num2)); System.out.println("感谢使用本程序!"); } }
在正常情况下,用户会按照系统的提示输入整数,除数不输入0,运行结果如图:
如果用户没有按照要求输入整数,如被除数输入非整数A,则程序运行时将会发生异常,运行结果如图:
如果用户没有按照要求进行输入,如除数输入0,则程序运行时将会发生异常,运行结果如图:
从结果中可以看出,一旦出现异常,程序将会立即结束,不仅计算和输出商的语句不被执行,而且输出“感谢使用本程序”的语句也不执行。应该如何解决这些异常呢?
if-else来解决异常问题
弊端:
1、代码臃肿
2、程序员要花很大精力“堵漏洞”
3、程序员很难堵住所有“漏洞”public class Test2 { public static void main(String[] args) { Scanner in = new Scanner(System.in); … System.out.print("请输入除数:"); int num2 = 0; if (in.hasNextInt()) { // 如果输入的除数是整数 num2 = in.nextInt(); if (0 == num2) { // 如果输入的除数是0 System.err.println("输入的除数是0,程序退出。"); System.exit(1); } } else { // 如果输入的除数不是整数 System.err.println("输入的除数不是整数,程序退出。"); System.exit(1); } … } }
什么是异常
异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序
什么是异常处理
Java编程语言使用异常处理机制为程序提供了错误处理的能力
Java中如何进行异常处理
Java中如何进行异常处理
try、catch、 finally、throw、throws
try-catch块
使用try-catch块捕获异常,分为三种情况
第一种情况 :try块中所有语句正常执行完毕,不会发生异常,那么catch块中的所有语句都将会被忽略
public void method(){ try { // 代码段(此处不会产生异常) } catch (异常类型 ex) { // 对异常进行处理的代码段 } // 代码段 }
第二种情况 :try语句块在执行中遇到异常,那么在try块中其余剩下的代码都将被忽略,系统会自动生成相应的异常对象,如果这个异常对象与catch中声明的异常类型相匹配,则相应的catch块将会被执行
public void method(){ try { // 代码段 1 // 产生异常的代码段 2 // 代码段 3 } catch (异常类型 ex) { // 对异常进行处理的代码段4 } // 代码段5 }
第三种情况 :try语句块在执行中遇到异常,如果这个异常对象与catch中声明的异常类型不匹配,程序会中断。
public void method(){ try { // 代码段 1 // 产生异常的代码段2 // 代码段 3 } catch (异常类型 ex) { // 对异常进行处理的代码段4 } // 代码段5 }
printStackTrace的堆栈跟踪功能显示出程序运行到当前类的执行流程
java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextInt(Scanner.java:2091)
at java.util.Scanner.nextInt(Scanner.java:2050)
at cn.jbit.exception.Test3.main(Test3.java:15)
在catch块中处理异常
加入用户自定义处理信息System.err.println("出现错误:被除数和除数必须是整数,除数不能为零。");
异常对象常用的方法处理信息
Error与Exception的区别
都继承与Throwable这个类
Error是java程序在编译阶段出现的问题,代码将无法通过编译
Exception是java程序在运行阶段时才出现的问题,能通过编译但是不能完整运行
常见的异常类型
多重catch块
一段代码可能会引发多种类型的异常,在上面计算并输出商的示例中,其实至少存在两种异常情况,输入非整数内容和除数为0,而我们统一按照Exception类型捕获。
如果要分别捕获,就可以使用多重catch块。
引发多种类型的异常
- 排列catch 语句的顺序:先子类后父类
- 发生异常时按顺序逐个匹配
- 只执行第一个与异常类型匹配的catch语句
public void method(){ try { // 代码段 // 产生异常(异常类型2) } catch (异常类型1 ex) { // 对异常进行处理的代码段 } catch (异常类型2 ex) { // 对异常进行处理的代码段 } catch (异常类型3 ex) { // 对异常进行处理的代码段 } // 代码段 }
try-catch-finally
在try-catch块后加入finally块
是否发生异常都执行
不执行的唯情况
存在return的try-catch-finally块
public void method(){ try { // 代码段 1 // 产生异常的代码段 2 } catch (异常类型 ex) { // 对异常进行处理的代码段3 return; }finally{ // 代码段 4 } }
面试题:
try-catch块中存在return语句,是否还执行finally块,如果执行,说出执行顺序?
1)finally的作用就是,无论出现什么状况,finally里的代码一定会被执行。
(2)如果在catch中return了,也会在return之前,先执行finally代码块。
(3)而且如果finally代码块中含有return语句,会覆盖其他地方的return。
(4)对于基本数据类型的数据,在finally块中改变return的值对返回值没有影响,而对引用数据类型的数据会有影响。
try-catch- finally块中, finally块唯一不执行的情况是什么?
(1)没有进入try代码块;
(2)System.exit()强制退出程序;
(3)守护线程被终止;
声明异常——throws
如果在一个方法体中抛出了异常,我们希望调用者能及时捕获异常,如何通知调用者?
Java语言中通过关键字throws声明某个方法可能抛出的各种异常。
throws可以同时声明多个异常,多个异常用逗号隔开。
如果把计算并输出商的任务封装在divide()方法中,并在方法的参数列表后通过throws声明了异常,然后在main()方法中调用该方法,此时main()方法就知道divide()方法中抛出了异常,可以采取以下两种方式进行处理。
方式1:调用者通过try-catch捕获并处理异常。
方式2:调用者通过throws继续声明异常。如果调用者不打算处理该异常,则可以继续通过throws声明异常,让上一级调用者处理异常。
main()方法声明的异常将由Java虚拟机来处理。public class Test7 { public static void divide() throws Exception { //可能出现异常的代码 } public static void main(String[] args) { try { divide(); } catch (Exception e) { e.printStackTrace(); } } // public static void main(String[] args) throws Exception { // divide(); // } }
抛出异常——throw
既然可以捕获到各种类型的异常,那么这些异常是在什么地方抛出的呢?
除了系统自动抛出异常外,在编程过程中,我们往往遇到这样的情形:有些问题是系统无法自动发现并解决的,如年龄不在正常范围内、性别输入不是“男”或“女”等,此时需要程序员而不是系统来自行抛出异常,把问题提交给调用者去解决。
Java语言中通过关键字throw来自行抛出异常。
抛出异常案例
public class Person { private String name = ""; // 姓名 private int age = 0; // 年龄 private String sex = "男"; // 性别 public void setSex(String sex) throws Exception { if ("男".equals(sex) || "女".equals(sex)) this.sex = sex; else { throw new Exception(“性别必须是\"男\"或者\"女\"!"); } } }
面试题
请说出throw和throws的区别?
throw和throws的区别表现在以下三个方面
- 作用不同: throw用于在程序中抛出异常; throws用于声明在该方法内抛出了异常。
- 使用的位置不同:throw位于方法体内部,可以作为单独语句使用; throws必须跟在方法参数列表后面,不能单独使用。
- 内容不同: throw抛出一个异常对象,而且只能是一个;throws后面跟异常类,而且可以跟多个异常类。
异常的分类
自定义异常
当JDK 中的异常类型不能满足程序的需要时,可以自定义异常类。
使用自定义异常的步骤
定义异常类:
继承Throwable类、继承Excepion 或者RuntimeException
异常处理原则
- 异常处理与性能
- 异常只能用于非正常情况
- 不要将过于庞大的代码块放在try中
- 在catch中指定具体的异常类型
- 需要对捕获的异常做处理