1、什么是异常
概念:程序在运行过程中出现的特殊情况
异常处理的必要性:任何程序都可能存在大量的未知问题、错误;如果不对这些问题进行正确处理,则可能导致程序的中断,造成不必要的损失。
2、异常的分类
Throwable:可抛出的,一切错误或异常的父类,位于java.lang包中
Error:JVM、硬件、执行逻辑错误、不能手动处理。
Exception:程序在运行和配置中产生的问题,可处理
RuntimeException:运行时异常,可处理,可不处理
CheckedException:受查异常,必须处理。
3、异常的产生
自动抛出异常:当程序在运行时遇到不符合规范的代码或结果时,会产生异常
手动抛出异常:语法:throw new 异常类型("实际参数");
产生异常结果:相当于遇到return语句,导致程序因异常而终止
4、异常的传递
异常的传递:按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈跟踪信息)。
受查异常:throws声明异常,修饰在方法参数列表后端。
声明时异常:因可处理可不处理,无需声明异常。
try{
可能出现异常的代码
}catch(Exception e){
异常处理的相关代码,如:getMessage()、printStackTrace()
}finally{
无论是否出现异常,都需执行的代码结构,常用于释放资源
}
异常的处理方式1:捕获异常
把可能发生异常的代码,存放到try语句块中 try{}
如果try中的代码产生了异常,则jvm会根据异常的原因,自动创建一个异常对象
try语句块中某行代码发生异常后,此行之后的代码将不会被执行到
当发生异常后,则进行catch捕获:
如果发生异常的类型和catch里捕获的异常类型一致,或者是其子类,则捕获到,进而执行catch语句块里的代码,捕获到异常后,程序就不会被中断,能继续运行
如果没有捕获到,则不执行catch语句块里的代码
import java.util.InputMismatchException;
import java.util.Scanner;
//现在我们需要算除法,定义一个除数,定义一个被除数,
//但是我们都知道被除数不能为0 java.lang.ArithmeticException
//这就算一个异常
//如果说我们写了一个非数字的传了进去 java.util.InputMismatchException
//这也会报一个异常
//如果在中间里写return,下边的代码依旧输出
public class Demo3 {
public static void main(String[] args) {
Scanner input = null;
try {
input = new Scanner(System.in);
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输入第二个数:");
int num2 = input.nextInt();
int result = num1/num2;
System.out.println("运算结果为:");
System.out.println(result);
//如果除数为0走这个
}catch(ArithmeticException ex) {
System.out.println("除数不能为0请重新输入");
如果输入的不是数字走这个
}catch(InputMismatchException ex) {
System.out.println("请输入数字进行传输");
//总有想不到的异常,这时候就用Exception进行接收走这条
}catch(Exception ex) {
System.out.println("输入有误请重新输入");
//无论有没有异常都会执行到的代码
}finally {
System.out.println("程序运行结束");
}
}
}
5、常见异常处理结构
try{ } catch{ }
try{ } catch{ } catch{ }
try{ } catch{ } finally{ }
try{ } catch{ } catch{ } finaly{ }
try{ } finally{ }
注:多重catch,遵循从子(小)到父(大)的顺序,父类异常在最后
6、自定义异常
概念:需继承Exception或Exception的子类,代表特定问题
经验:异常类型名称望文生义,可在发生特定问题时抛出对应的异常
常用构造方法:
无参数构造方法
String message参数的构造方法
异常的处理方式2:
1)抛出异常
throws 抛出 抛给调用
import java.util.InputMismatchException;
import java.util.Scanner;
//抛出异常,当别人调用该方法,但是该方法会产生异常时,选择在方法中抛出,在调用的类中决定继续抛出
//还是捕获
//这个方法还是会出异常,这个时候我们就要在该方法中throws 异常类型 如果什么都不知道就抛出父类
//Exception
public class Com {
public void test() throws InputMismatchException{
Scanner input = new Scanner(System.in);
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输出第二个数:");
int num2 = input.nextInt();
System.out.println("输出的结果为:");
int result = num1 / num2;
System.out.println(result);
}
}
import java.util.InputMismatchException;
//虽然此时的main的方法会将异常抛出,但是再往上抛出就是虚拟机了,所以最好还是要接收一下
public class test1 {
public static void main(String[] args) throws InputMismatchException{
Com com = new Com();
com.test();
}
}
import java.util.InputMismatchException;
import java.util.Scanner;
//抛出异常,当别人调用该方法,但是该方法会产生异常时,选择在方法中抛出,在调用的类中决定继续抛出
//还是捕获
//这个方法还是会出异常,这个时候我们就要在该方法中throws 异常类型 如果什么都不知道就抛出父类
//Exception
public class Com {
public void test() throws InputMismatchException{
Scanner input = new Scanner(System.in);
System.out.println("请输入第一个数:");
int num1 = input.nextInt();
System.out.println("请输出第二个数:");
int num2 = input.nextInt();
System.out.println("输出的结果为:");
int result = num1 / num2;
System.out.println(result);
}
}
import java.util.InputMismatchException;
//虽然此时的main的方法会将异常抛出,但是再往上抛出就是虚拟机了,所以最好还是要接受一下
public class test1 {
public static void main(String[] args) {
try{
Com com = new Com();
com.test();
}catch(InputMismatchException ex) {
System.out.println("发生异常");
}
}
}
throw new 异常
//写一个支付的方法 Pay
public class Pay {
public void pay(int money) throws Exception{
if(money <= 0) {
//手动抛出异常
//就是我自己知道一定会有异常发生,但是不知道是什么异常
//就用throw new Eception来创造一个
throw new Exception();
}else {
System.out.println("成功支付了" + money+"元");
}
}
}
public class test1 {
public static void main(String[] args) {
try {
Pay pay = new Pay();
pay.pay(5);
}catch(Exception ex) {
System.out.println("请重新输入");
}
}
}
2)自定义异常
//写一个方法来收取异常继承Exception
public class PayException extends Exception{
//写构造器
public PayException() {
}
public PayException(String meg) {
super(meg);
}
}
public class Pay {
//抛出异常 但是抛给自己写的类
public void pay(int money) throws PayException{
if(money <= 0) {
throw new PayException("支付金额不正确");
}else {
System.out.println("支付成功");
}
}
}
public class test1 {
public static void main(String[] args) {
try {
Pay pay = new Pay();
pay.pay(0);
}catch(PayException ex) {
// ex.getMessage() 就是用来接收pay方法里异常的
System.out.println("异常原因:" + ex.getMessage());
}
}
}
7、方法重写
带有异常声明的方法重写:
方法名、参数列表、返回值类型必须和父类相同。
子类的访问修饰符符合父类相同或是比父类更宽
子类中的方法,不能抛出比父类更多。更宽的异常