Java异常

一、基本概念

异常 :指的是程序在执行过程中,出现的非正常情况,最终会导致JVM的非正常停止。 在Java等面向对象的编程语言中,异常本身就是一个类,产生异常就是创建一个异常对象并抛出该异常对象。Java处理异常的方式是中断处理。

【注】异常指的并不是语法错误。因为语法错了,编译就不会通过,不会产生字节码文件,程序根本不能运行。而异常指的是程序在执行过程中出现的非正常情况。

异常的继承体系:异常机制其实是帮助我们找到程序中的问题,异常的根类是 java.lang.Throwable ,其下有两个子类: java.lang.Errorjava.lang.Exception ,我们平常所说的异常就是指 java.lang.Exception

  • Error:表示严重错误,程序员无法处理,只能事先避免,好比绝症。

  • Exception:表示异常,异常产生后程序员可以通过编写代码的方式纠正,使程序继续运行,程序员是能处理的。好比感冒、阑尾炎。

异常的分类:根据在编译期还是运行期去检查异常可分为编译时异常和运行时异常。

  • 编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)

  • 运行时期异常:runtime异常。在运行时期,检查异常。在编译时期,运行异常不会被编译器检测,即编译器不会报错。(如数学异常)

异常的产生过程解析:以如下的例子为例

二、异常的处理

1. 抛出异常throw

​ 在Java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。

​ 使用格式:throw new 异常类名(参数); 参数是程序员自己编写的一些提示信息。throw用在方法内,用来抛出一个异常对象,将这个异常对象传递给调用者,并结束当前方法的执行。

举例:

public class ThrowDemo { 
	public static void main(String[] args) { 
		// 创建一个数组 
		int[] arr = {2,4,52,2}; 
		//根据索引找对应的元素 
		int index = 4; 
		int element = getElement(arr, index); 
		System.out.println(element); 
		System.out.println("over"); 
	}
	// 根据索引找到数组中对应的元素 
	public static int getElement(int[] arr,int index){ 
		// 判断索引是否越界 
		if(index<0 || index>arr.length‐1){ 
			// 判断条件如果成立,则使用throw抛出异常对象并将该异常对象传递给调用者,并结束当前方法的执行
			throw new ArrayIndexOutOfBoundsException("哥们,角标越界了~~~"); 
		}
		int element = arr[index]; 
		return element; 
	} 
}

​ 那么对于调用者来说,该怎么处理传递过来的异常对象呢?一种是进行捕获处理,另一种就是继续将问题声明出去,使用throws声明处理。

2. 声明异常throws

​ 如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。

​ 关键字throws运用于方法声明之上,用于表示当前方法不处理异常对象,而是继续把该异常对象传递给自己上一级的调用者。如果当前方法已经是main()方法了,则会把这个异常对象交给JVM来处理。JVM的做法是:打印异常的跟踪栈消息,并终止程序。

3. 捕获异常try...catch

​ 捕获异常的语法如下:

try{ 
	编写可能会产生异常的代码 
}catch(异常类型 e){ 
	处理异常的代码 
	//记录日志/打印异常信息/继续抛出异常
}

如何获取异常信息:

Throwable根类中定义了一些查看的方法:

  • public void printStackTrace() :打印异常的详细信息。包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace()方法。

  • public String getMessage() :获取发生异常的原因。 向用户提示错误的原因。

4. finally代码块

​ 有一些特定的代码无论异常是否发生,都应该要执行,但是因为异常会引发程序跳转,可能会导致这些语句执行不到。而finally代码块就是解决这个问题的,在finally代码块中存放的代码是一定会被执行的。

什么样的代码必须最终执行?

​ 当我们在try语句块中打开了一些物理资源(如磁盘文件/网络连接/数据库连接等),我们都得在使用完之后关闭打开的资源。

三、有关于异常的一些注意事项

  1. 当有多个异常时,使用try...catch的方式又该如何处理呢?

    我们一般采用一次捕获多次处理的方式,格式如下:

    try{ 
    	编写可能会出现异常的代码 
    }catch(异常类型A e){ 当try中出现A类型异常,就用该catch来捕获
    	处理异常的代码 
    	//记录日志/打印异常信息/继续抛出异常 
    }catch(异常类型B e){ 当try中出现B类型异常,就用该catch来捕获
    	处理异常的代码 
    	//记录日志/打印异常信息/继续抛出异常 
    }
    

    【注】这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类的继承关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

  2. 编译时异常必须进行处理,要么使用try...catch捕获异常,要么通过throws关键字将异常继续声明出去由该方法的调用者来处理,否则编译通不过。而运行时异常一般可以不处理。

  3. 当出现异常时,不要紧张,把异常的类名(例如 ArrayIndexOutOfBoundsException),拷贝到API中去查看。

原文地址:https://www.cnblogs.com/jiajun107/p/12983618.html