本课目标:异常

发布于:2023-02-02 ⋅ 阅读:(333) ⋅ 点赞:(0)

目录

生活中的异常

程序场景

if-else来解决异常问题

什么是异常

 什么是异常处理

Java中如何进行异常处理

try-catch块

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

 Error与Exception的区别

 常见的异常类型

多重catch块

引发多种类型的异常

 try-catch-finally

面试题:

try-catch块中存在return语句,是否还执行finally块,如果执行,说出执行顺序?

try-catch- finally块中, finally块唯一不执行的情况是什么?

 声明异常——throws

 抛出异常——throw

抛出异常案例

面试题

请说出throw和throws的区别?

异常的分类

自定义异常

异常处理原则

 总结


 

生活中的异常

正常情况下,小王每日开车去上班,耗时大约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的区别表现在以下三个方面

  1. 作用不同: throw用于在程序中抛出异常; throws用于声明在该方法内抛出了异常。
  2. 使用的位置不同:throw位于方法体内部,可以作为单独语句使用; throws必须跟在方法参数列表后面,不能单独使用。
  3. 内容不同: throw抛出一个异常对象,而且只能是一个;throws后面跟异常类,而且可以跟多个异常类。

异常的分类

自定义异常

当JDK 中的异常类型不能满足程序的需要时,可以自定义异常类。
使用自定义异常的步骤


定义异常类:

继承Throwable类、继承Excepion 或者RuntimeException

异常处理原则

  • 异常处理与性能
  • 异常只能用于非正常情况
  • 不要将过于庞大的代码块放在try中
  • 在catch中指定具体的异常类型
  • 需要对捕获的异常做处理

 总结


网站公告

今日签到

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