异常(异常的捕捉和解决)

发布于:2022-11-09 ⋅ 阅读:(708) ⋅ 点赞:(0)

学习目标:

理解异常概念和Java异常处理机制

熟练使用try-catch-finally处理异常

熟练使用throw、throws抛出异常

熟悉Java异常体系结构

了解自定义异常


学习内容:

生活中的异常

 程序场景

以下程序运行时会出现错误吗?

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("感谢使用本程序!");
	}
}

首先上述代码编译时肯定不会出现问题,但是在运行时可能会会出现一些问题。

程序分析

1.在正常情况下,用户会按照系统的提示输入整数,除数不输入0,运行结果如图:

 2.如果用户没有按照要求输入整数,如被除数输入非整数A,则程序运行时将会发生异常,运行结果如图:

3. 如果用户没有按照要求进行输入,如除数输入0,则程序运行时将会发生异常,运行结果如图:

 从结果中可以看出,一旦出现异常,程序将会立即结束,不仅计算和输出商的语句不被执行,而且输出“感谢使用本程序”的语句也不执行。应该如何解决这些异常呢?

1.尝试通过if-else来解决异常问题

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);
		}
		…
	}
}

弊端:

1、代码臃肿

2、程序员要花很大精力“堵漏洞”

3、程序员很难堵住所有“漏洞”

什么是异常

 什么是异常处理

 Java中如何进行异常处理

Java的异常处理是通过5个关键字来实现的:  try、catch、 finally、throw、throws

 

try-catch块5-1

使用try-catch块捕获异常,分为三种情况

第一种情况 :try块中所有语句正常执行完毕,不会发生异常,那么catch块中的所有语句都将会被忽略

public void method(){
try {
  // 代码段(此处不会产生异常)
} catch (异常类型 ex) {
      // 对异常进行处理的代码段
}
 // 代码段
}

try-catch块5-2

二种情况 :try语句块在执行中遇到异常,那么在try块中其余剩下的代码都将被忽略,系统会自动生成相应的异常对象,如果这个异常对象与catch中声明的异常类型相匹配,则相应的catch块将会被执行

public void method(){
try {
      // 代码段 1
      // 产生异常的代码段 2
      // 代码段 3
} catch (异常类型 ex) {
      // 对异常进行处理的代码段4
}
// 代码段5
}

 try-catch块5-3

printStackTrace的堆栈跟踪功能显示出程序运行到当前类的执行流程 

 try-catch块5-4

第三种情况 :try语句块在执行中遇到异常,如果这个异常对象与catch中声明的异常类型不匹配,程序会中断。

public void method(){
try {
     // 代码段 1
     // 产生异常的代码段2
     // 代码段 3
} catch (异常类型 ex) {
     // 对异常进行处理的代码段4
}
// 代码段5
}

 try-catch块5-5

在catch块中处理异常

加入用户自定义处理信息

System.err.println("出现错误:被除数和除数必须是整数,除数不能为零。");

常见的异常类型

异 常 类 型 说    明
Exception 异常层次结构的父类
ArithmeticException 算术错误情形,如以零作除数
ArrayIndexOutOfBoundsException 数组下标越界
NullPointerException 尝试访问 null 对象成员
ClassNotFoundException 不能加载所需的类
IllegalArgumentException 方法接收到非法参数
ClassCastException 对象强制类型转换出错
NumberFormatException 数字格式转换异常,如把"abc"转换成数字

多重catch块

一段代码可能会引发多种类型的异常,在上面计算并输出商的示例中,其实至少存在两种异常情况,输入非整数内容和除数为0,而我们统一按照Exception类型捕获。 如果要分别捕获,就可以使用多重catch块。

引发多种类型的异常

排列catch 语句的顺序:先子类后父类

发生异常时按顺序逐个匹配

只执行第一个与异常类型匹配的catch语句

public void method(){
try {
     // 代码段
     // 产生异常(异常类型2)
} catch (异常类型1 ex) {
     // 对异常进行处理的代码段
} catch (异常类型2 ex) {
     // 对异常进行处理的代码段
} catch (异常类型3 ex) {
     // 对异常进行处理的代码段
}
// 代码段
}

 try-catch-finally 2-2

存在return的try-catch-finally块

public void method(){
try {
     // 代码段 1
     // 产生异常的代码段 2
} catch (异常类型 ex) {
     // 对异常进行处理的代码段3
     return;
}finally{
      // 代码段 4
}
}

 

异常:
    想要学好Java代码、开发、积累异常处理经验,一定要做好每个异常的笔记(描述、发生的原因、如何处理,总结处理的原理或者经验)
    Java中讲的异常通常指的是能通过编译,但是在运行阶段因为某些原因发生了不正常的情况,导致程序运行中断
    Java中还有一种非正常情况,也就是Error,通常指的是在编译阶段就已经发生问题了,在IDEA中编译不通过的时候会直接在代码行报红色波浪线
简单举例:
    Exception in thread "main" java.lang.ArithmeticException: / by zero
        at com.oop.day12.CalcNum.main(CalcNum.java:17)
    凡是看到控制台有Exception,就表示程序有异常
    java.lang.ArithmeticException:表示异常的类型,重点是后面的类,比如这里的ArithmeticException
    : / by zero,冒号后面表示对异常的描述,这里的意思是 “除以了0”
    at com.oop.day12.CalcNum.main(CalcNum.java:17) 表示异常发生在哪个包下的哪个类,哪个方法,
        后面的数字17表示发生在CalcNum类的第17行

    try:尝试执行可能出现异常的代码【try只能尝试可能出现Exception的代码,如果是发生Error的代码即使try也没有用,依然无法通过编译】
    catch:捕捉异常。只能捕捉他对应的try中代码的异常,如果有一行代码可能发生异常,但是没有写在这个catch对应的try中,那么这个catch将无法捕捉这行代码的异常
        也就是说catch要想捕捉某些代码的异常,那么就必须将这些代码放在try中去尝试执行

        catch捕捉的事try中发生的具体的某个异常,如果catch捕捉的是A类异常,而try没有发生异常或者发生了A类以外的异常,那么这个catch是不生效的
        catch有两种写法
            1:}catch (ArithmeticException | InputMismatchException arithmeticException){
                System.out.println("除数不能为0!!!");
            }
            这种写法表示catch捕捉两种异常,但是发生两种异常之后的处理机制是一样的
            2.}catch (ArithmeticException arithmeticException){
                System.out.println("除数不能为0!!!");
            }catch (InputMismatchException inputMismatchException){
                System.out.println("输入的内容格式不正确!!!");
            }
            这种写法也表示catch捕捉两种异常,但是发生异常之后,各自使用各自的处理机制

        多重catch时,会根据try中发生的异常类型对多重catch按照顺序逐个匹配,当匹配上时,执行相应的处理逻辑,
        如果都不匹配,但是想有其它的处理机制,可以在最后捕捉异常的父类:Exception
        所以多重catch的写法一定是先子后父
    finally:最终的。try中无论是否发生异常,都将在try中的代码执行完之后,去执行finally中的代码
        无论try中的异常是否能够被catch捕捉到,finally中的代码都会被执行
        对比:代码写在finally里和写在try-catch-finally结构外
            当try中不发生异常或者发生的异常被catch捕捉到,那么finally中的代码和finally外的代码都会继续执行
            当try中发生的异常没有被catch捕捉到,finally中的代码依然会被执行,但是finally外的代码将不再执行
    throw:在方法体中 手动 抛出代码发生的异常
    throws:在方法头上声明该方法可能会抛出的异常

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到