异常
1 概述
异常是一些用来封装错误信息的对象
它由异常的类型、提示信息、报错的行号提示三部分组成
2 异常的继承结构
3 异常的处理方式
当程序中遇到了异常,通常有两种处理方式:捕获或者向上抛出
当一个方法抛出异常,调用位置可以不做处理继续向上抛出,也可以捕获处理异常
大家可以结合生活中的例子:如果工作中遇到了问题,我们可以选择自己处理(捕获),或者交给上级处理(抛出)
对于不想现在处理或者处理不了的异常可以选择向上抛出
方式:在方法上设置异常的抛出管道,即:
在可能会会发生异常的方法上添加代码:
throws 异常类型
例如:void method1 throws Exception1,Exception2,Exception3{ }
TIPS:方法上有默认的异常管道:RuntimeException
4 练习:异常测试
创建包: cn.tedu.exception
创建类: ExceptionDemo.java
package cn.tedu.exception;
import java.util.InputMismatchException;
import java.util.Scanner;
/*本类用作测试异常的入门案例*/
public class ExceptionDemo {
public static void main(String[] args) {
//method1();//调用method1方法--人为暴露异常--看看异常长啥样
//method2();//调用method2方法--异常解决方案1--捕获处理--自己解决
//method3();//调用method3方法--异常解决方案2--向上抛出--交给调用者来解决
f();//为了写一个标准的写法,在main()调用之前,处理掉异常
}
private static void f() {
try{
method3();
}catch(Exception e){
System.out.println("请输入正确的数据!");
}
}
/*如果一个方法抛出了异常,那么谁调用这个方法,谁就需要处理这个异常
* 这里的处理也有两种方案:捕获解决和继续向上抛出
* 但是注意:我们一般会在main()调用之前解决掉异常
* 而不是把问题抛给main(),因为没人解决了,详见本类f()调用method3()
* */
//6.创建method3(),异常解决方案2
/*异常抛出的格式:在小括号与大括号之间写:throws 异常类型
* 如果有多个异常,使用逗号分隔即可*/
// private static void method3()
// throws InputMismatchException,ArithmeticException,Exception{ private static void method3()
private static void method3() throws Exception{
//7.1复写刚刚的代码
System.out.println("请输入您要计算的第一个整数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请输入您要计算的第二个整数:");
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}
/*异常捕获处理的格式:
* try{
* 可能会抛出异常的代码
* }catch(异常类型 异常的名字){
* 捕获到了异常,进行处理的解决方案
* }
* */
//4.创建方法用来捕获处理异常--自己处理
private static void method2() {
//5.1按照捕获处理的语法提供异常解决方案一
/*4.try中放着的是可能会出现异常的代码*/
/*5.如果发生了异常,会被catch捕获,执行之前catch中提供的解决方案*/
try{
//5.2复写一下刚刚的代码
System.out.println("请输入您要计算的第一个整数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请输入您要计算的第二个整数:");
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
//5.3捕获处理异常
}catch(InputMismatchException e){//注意要导包
System.out.println("请输入规定的整数类型!");
}catch(ArithmeticException e){
System.out.println("除数不能为0是我们的错,请您再输一次~");
}catch(Exception e){
System.out.println("您输入的不对!请重新输入!");
}
/*6.try-catch可以嵌套,如果有多种异常类型需要特殊处理的话*/
/*7.这就是多态最为经典的一种用法,我们并不关心子类具体的类型
* 而是将所有子类统一当作父类类型来处理,提供通用的解决方案*/
}
private static void method1() {
//1.提示并接收用户输入的第一个数
System.out.println("请输入您要计算的第一个整数:");
int a = new Scanner(System.in).nextInt();
//2.提示并接收用户输入的第二个数
System.out.println("请输入您要计算的第二个整数:");
int b = new Scanner(System.in).nextInt();
//3.直接打印这两个数除法的结果
System.out.println(a/b);
//输入3和3.5,报错:InputMismatchException--输入不匹配异常
//输入17和0,报错:ArithmeticException--算术异常,除数不能为0是数学规定
/*1.不要害怕BUG,真正的勇士敢于直面自己写的BUG*/
/*2.学会看报错的信息提示,确定自己的错误方向*/
/*3.学会看报错的行号信息,确定自己报错的位置,哪里不对点哪里
* 注意:源码不会错,要看的是自己写的代码*/
}
}
5 拓展1 catch 和 throws
异常处理只有两种方式: catch 和 throws,所以必须二选一
由于Java语法本身的特点,需要开发者事先考虑异常如何处理,也就是我们常说的:“未雨绸缪”
对于初级开发者来说,我们可能会捕获,但不处理异常
try {
…
} catch(Exception e) {
}
底层异常,应该向前抛到前面处理
经验少时,不知道该在什么位置捕获处理,应该选择 throws
但是大家需要注意,在异常抛出时,有些异常比如运行时异常,可能并不会强制要求抛出此异常,调用时也没有报错显示需要额外处理,这个时候就需要大家平时多积累,掌握良好的编码习惯了,手动添加代码进行预处理,增强程序的健壮性了。
6 拓展2
程序错误分为三种:
编译错误(checked异常);
运行时错误(unchecked异常);
逻辑错误;
- 编译错误是因为程序没有遵循语法规则,编译程序能够自己发现并且提示我们错误的原因和位置,这个也是大家在刚接触编程语言最常遇到的问题。
- 运行时错误是因为程序在执行时,运行环境发现了不能执行的操作。
- 逻辑错误是因为程序没有按照预期的逻辑顺序执行。异常也就是指程序运行时发生错误,而异常处理就是对这些错误进行处理和控制。
其实我们还可以手动针对逻辑错误执行异常的抛出动作,大家可以理解成方法return,只不过此处我们返回的是异常,格式:
if(逻辑错误有异常){
AException e = new AException(“提示消息”);
throw e;
}
package cn.tedu;
import java.util.Scanner;
public class TestThrow {
public static void main(String[] args) {
method4();
}
public static void method4(){
//1.复写刚刚可能会发生异常的代码
System.out.println("请输入您要计算的第一个数据:");
int a = new Scanner(System.in).nextInt();
System.out.println("请输入您要计算的第二个数据:");
int b = new Scanner(System.in).nextInt();
try{
double result = divide(a,b);
System.out.println(result);
//System.out.println(a/b);
}catch (ArithmeticException e){
System.out.println("不能除0是我们的错,请鞭笞我们吧!");
}
}
private static double divide(int a,int b) {
if(b == 0){
ArithmeticException e = new ArithmeticException("/ by zero");
throw e;//类似于return e;
}
return a/b;
}
}
6 拓展3
throws 与 throw 的区别
throws
用在方法声明处,其后跟着的是异常类的名字
表示此方法会抛出异常,需要由本方法的调用者来处理这些异常
但是注意:这只是一种可能性,异常不一定会发生
throw
用在方法的内部,其后跟着的是异常对象的名字
表示此处抛出异常,由方法体内的语句处理
注意:执行throw一定抛出了某种异常