JAVA异常学习总结

异常概述

一、 认识异常

异常是指在程序运行过程中发生的不正常事件,比如所需文件找不到、网络连接不通或网络中断、数组下标越界、类型转换异常等。异常会中断正在运行的程序。

 可以通过下面的代码认识异常:
import java.util.Scanner;

/**
 * 演示程序中的异常。
 * @author administrator
 */
public class Test1 {
	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(num1+"/"+ num2 +"="+ num1/ num2);
		System.out.println("感谢使用本程序!");
	}
}

这段代码中,此处将 num1 和 num2 都以整型的形式输出。
正常情况下,用户会按照系统的提示输入整数,除数不能为0,但是如果用户没有按照要求进行输入,如除数输入了非整型,则程序运行时将会发生异常,输出结果如图所示:
在这里插入图片描述
如果输入0,则程序运行时也会发生异常,输出结果如图所示:
在这里插入图片描述
从运行结果可以看出,一旦出现异常程序将会立刻结束,计算和输出的语句则不会执行,也可以通过if-else语句对各种异常情况进行判断处理,代码如下所示:

import java.util.Scanner;

/**
 * 传统处理程序中的异常。
 * @author administrator
 */
public class Test2 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		System.out.print("请输入被除数:");
		int num1 = in.nextInt();
		System.out.print("请输入除数:");
		int num2 = 0;
		if (in.hasNextInt()) { // 如果输入的除数是整数
			num2 = in.nextInt();
			if (0 == num2) { // 如果输入的除数是0
				System.err.println("输入的除数是0,程序退出。");
				System.exit(1);
			}
			System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
			System.out.println("感谢使用本程序!");
		} else { // 如果输入的除数不是整数
			System.err.println("输入的除数不是整数,程序退出。");
			System.exit(1);
		}
		
	}
}

但是,通过if-else进行异常处理,有以下几个缺点:

  1. 代码臃肿,加入了大量的异常情况判断和处理代码。
  2. 容易分散过多的精力处理异常,影响开发效率。
  3. 很难举例所有的异常情况。
  4. 异常处理代码和业务代码交织在一起,影响代码可读性,容易加大日后的程序的维护难度。

二、Java异常体系结构

Java中的异常有很多种类型,异常体系结构如图:
在这里插入图片描述
所有异常类型都是Throwable类的子类,它派生了两个子类:Error类和Exception类。

三、Java异常处理
Java的异常处理是通过5个关键字来实现的:try、catch、 finally、throw、throws。
(1)try:执行可能产生异常的代码
(2)catch:用来捕获异常
(3)finally:无论是否发生异常,代码总能执行
(4)throw:手动抛出异常,可写在try、catch、 finally中以及代码块之外
(5)throws:声明方法可能要抛出的各种异常 ,放在参数旁边

  1. 使用try-catch处理异常
    使用try-catch块捕获异常,分为三种情况:
    (1)第一种情况 :正常
public void method(){
         try {
                  // 代码段(此处不会产生异常)
         } catch (异常类型 ex) {
                 // 对异常进行处理的代码段
         }
         // 代码段
}

(2)第二种情况:出现异常

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

异常是一种特殊的对象,类型为java.lang.Exception或其子类。
如果try语句块在执行过程中发现异常,并且这个异常与catch语句块中声明的异常类型匹配,那么try中剩下的代码都将被忽略,而catch中的语句继续执行。
当在被除数输入了A,则抛出InputMismatchException异常,由InputMismatchException是Exception的子类,程序将忽略try语句块中剩下的代码而执行catch语句块。输出结果如图所示:
在这里插入图片描述
如果输入除数为0,输出结果如下图所示:
在这里插入图片描述
(3)第三种情况:异常类型不匹配

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

如果try语句块在执行过程中发生异常,而抛出的异常在catch语句块中没有被声明,那么方法立刻退出。
在catch语句块中可以加入用户自定义处理信息,也可以调用异常对象的方法输出异常信息,常用方法如下:
(1)void getMessage():返回异常的堆栈信息。堆栈信息包括程序运行到当前类的执行流程,它将输出从方法调用处到异常抛出处的方法调用序列。
()String getMessage():返回异常信息描述字符串,该字符串描述了异常产生的原因,是printStacktrace()输出信息的一部分。

注意:如果try语句块在执行过程中发生异常,try语句块中剩下的代码都将被忽略,系统会自动生成相应 的异常对象,包括异常的类型、异常出现时程序的运行状态及对该异常的详细描述。如果这个异常对象与catch语句块中声明的异常匹配类型匹配,会把该异常对象赋给catch后面的异常参数,相应的catch语句将会被执行。

  • 在catch块中处理异常:加入用户自定义处理信息
    System.err.println("出现错误:被除数和除数必须是整数 ");

  • 调用方法输出异常信息:e.printStackTrace();

  • 异常对象常用的方法:
    ](https://img-blog.csdnimg.cn/2019050521564975.png)

  • 常见的异常类型
    在这里插入图片描述

  1. try-catch-finally处理异常
    如下面代码所示:
import java.util.InputMismatchException;
import java.util.Scanner;
public class Text7 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("请输入被除数:");
        try{
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            if(num1<num2){
                return;
            }
            System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
        }catch (InputMismatchException e){
            System.err.println("被除数和除数必须为整数");
        }catch (ArithmeticException e){
            System.err.println("除数不能为0");
        }catch (Exception e){
            System.err.println("其他未知异常");
        }finally {
            System.out.println("程序继续");
            System.out.println("程序结束");
        }
    }
}

(1) 在try-catch块后加入finally块
特点:是否发生异常都执行;不执行的唯一情况,如下图所示:
(2)存在return的try-catch-finally块
如下面代码所示:

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

try-catch- finally语句块的执行流程大致分为如下两种情况:

  • 如果try语句块中所有语句正常执行完毕,finally 语句块也会被执行。例如,当在控 制台输入两个数字时,示例4中的try语句块中的代码将正常执行,不会执行catch语句块中的代码,但是finally语句块中的代码将被执行。
  • 如果try语句块在执行过程中发生异常,无论这种异常能否被catch语句块捕获到,都将执行finally 语句块中的代码。例如,当在控制台输入的除数为0时,示例4中的try语句块中将抛出异常,进入catch语句块,最后finally 语句块中的代码也将被执行。

注意:即使在catch语句块中存在return语句,finally语句块中的语句也会执行。发生异常时的执行顺序是,先执行catch语句块中return之前的语句,再执行finally语句块中的语句,最后执行catch语句块中的return语句退出。

  1. 多重catch块
    1> 排列catch 语句的顺序:先子类后父类
    2> 发生异常时按顺序逐个匹配
    3> 只执行第一个与异常类型匹配的catch语句

    在计算并输出商的示例中,至少存在两种异常情况,输入非整数内容和除数为0,可使用多重catch 语句块分别捕获并处理对应异常。
    一段代码可能会引发多种类型的异常,这时,可以在一个try语句块后面跟多个catch语句块分别处理不同的异常。但排列顺序必须是从子类到父类,最后一个一般都是Exception类。因为按照匹配原则,如果把父类异常放到前面,后面的catch语句块将不会被执行机会。
    运行时,系统从上到下分别对每个catch语句块处理的异常类型进行检测,并执行第一个与异常类型匹配的catch语句。执行其中的一条catch语句之后, 其后的catch可将被忽略。

  2. 使用throws声明抛出异常

    (1)如果在一个方法体中抛出了异常,并希望调用者能够及时地捕获异常,Java 语言中通过关键字throws声明某个方法可能抛出的各种异常以通知调用者。throws可以同时声明多个异常,之间由逗号隔开。
    (2) 如下面代码所示,把计算并输出商的任务封装在了divide() 方法中,并在方法的参数列表后通过throws声明抛了异常,然后在main()方法中调用该方法,此时main()方法就知道divide()方法中抛出了异常,可以采用如下两种方式进行处理。
    1> 通过try-catch捕获并处理异常。
    2>通过throws继续声明变量,如果调用者不知道如何处理该异常,可以继续通过throws声明异常,让上一级调用者处理异常。main()方法声明的异常将由Java虚拟机来处理。

import java.util.InputMismatchException;
import java.util.Scanner;

public class Text2 {
    public static void main(String[] args) {
        try{
            divide();
        }catch (InputMismatchException e){
            System.err.println("被除数和除数必须为整数");
        }catch (ArithmeticException e){
            System.err.println("除数不能为0");
        }catch (Exception e){
            System.err.println("其他未知异常");
        }finally {
            System.out.println("程序继续");
            System.out.println("程序结束");
        }
    }
    public static void divide() throws Exception{
        Scanner in = new Scanner(System.in);
        System.out.print("请输入被除数:");
        int num1 = in.nextInt();
        System.out.print("请输入除数:");
        int num2 = in.nextInt();
        System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
    }
}
  1. 使用throw抛出异常
    除了系统自动抛出异常外,在编程过程中,有些问题是系统无法自动发现并解决的,如年龄不在范围内,性别输入不是“男”或“女”,所以需要在 方法内部通过throw抛出异常,如下面代码所示:
public class Person {
	private String name = "";// 姓名
	private int age = 0;// 年龄
	private String sex = "男";// 性别
	/**
	 * 设置性别。
	 * @param sex 性别
	 * @throws Exception
	 */
	public void setSex(String sex) throws Exception {
		if ("男".equals(sex) || "女".equals(sex))
			this.sex = sex;
		else {
			throw new Exception("性别必须是“男”或者“女”!");
		}
	}
	/**
	 * 打印基本信息。
	 */
	public void print() {
		System.out.println(this.name + "(" + this.sex 
				+ "," + this.age + "岁)");
	}
}

//输出基本信息

public class Test8 {
	public static void main(String[] args) {
		Person person = new Person();
		try {
			person.setSex("Male");
			person.print();
		} catch (Exception e) {			
			e.printStackTrace();
		}
	}
}

输出结果如下所示:
在这里插入图片描述

*注意:
throw 和 throws的区别:

  • 作用不同:throw用于程序员自行产生并抛出异常,throws用于声明该方法内抛出了异常。
  • 使用位置不同:throw用于方法体内部,可以作为单独语句使用;throws必须跟在方法参数列表的后面,不能单独使用。
  • 内容不同:throw抛出一个异常对象,只能是一个;throws后面跟异常类,可以跟多个。*
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值