异常1——初识(Java)

在编程过程中,我们所写的代码会遇到很多问题,有些语法上的错误或是逻辑上的错误我们都是可以在编译之后或是运行之后进行更改的,然而有些错误是不知道什么时候出错,在编译过程中我们发现了也不能更改的错误。那么这个时候我们就要做相应的处理,以确保一个程序能继续运行。

先来看一个例子:

我们发现在打印10/0这个结果的时候,编译时并没有报错,但是运行时出现了ArithmeticException这样的一个异常,并且程序就停止了,这样如果该句后面还有其他代码语句的话,就不会被执行到。当然在我们编写代码的过程中,不仅仅只是这一个异常,还有很多其他的异常,如在介绍数组时出现的ArrayIndexOutOfBoundsException(数组角标溢出异常)、在介绍String类时出现的StringIndexOutOfBoundsException(字符串角标溢出异常)和递归时出现的StackOverFlowError(栈溢出错误),可见异常也是分好多种类的,相应的也有它相应的体系

但是不管分多少中异常或是错误,都是以Exception或者Error结尾的。随机打开一个出现的异常的源码,向上翻找,发现他的最终父类都是Throwable这个类,这个类还实现了其他的接口,并没有继承其他类。翻看该类的API,我们发现:

它的直接子类就只有Exception和Error这两个类,因此可知运行时出现的错误打印的异常或者错误都是从这两个子类继承过来的。那么这两个到底是什么呢?

Error:是由虚拟机直接抛出的严重性错误(内存中的问题), 因为我们不能解决内存中的问题,但这在编译时或者运行中是不会出现的,而是在运行之后出现的错误,一旦出现这种错误,我们在编译时或者运行中是无法解决的,因此要在运行后,根据虚拟机出现的错误去改写我们所写的代码,而不能进行捕获。

Exception:是指一般性的错误,可以由虚拟机直接抛出,但是不建议这样做,如果是在编译时出现这样的异常,我们需要向上声明或是捕获,在运行后出现这样的异常,一般改代码的语句或是进行捕获。

而在Exception中,它的实现子类也有很多,如:

这么多类中可以分为两大类:RuntimeException类和Exception及其其他子类。

RuntimeException类:运行时异常,想处理就处理,如果不处理则程序中断;

Exception及其其他子类 :编译时异常,需要被处理。

那么如何对异常进行处理,Java提供两种解决的办法:1.声明异常,事先告知调用者该函数内部可能会出错,然后由调用者自行决断,通常声明异常用throws 异常的类或者throw 异常的对象;2.捕获异常,将该问题获取到,然后自己进行处理,不再向上声明。

public class Main {
	public static void main(String[] args) {
		
		int[] a=new int[10];
		int index=10;
		show(a,index);
	}
	public static void show(int[] a,int index){
       //方法一:声明异常对象
            /*	if(a==null){
		     throw new NullPointerException("数组为空");  //如果数组为空,操作不当可能会出现空指针异常,这里可以声明一个空指针异常的对象,注意用到了new是对象,然后提示数组为空
		}
		if(index<0||index>=a.length){
		     throw new ArrayIndexOutOfBoundsException(); //对数组的角标操作不当,会出现数组角标越界异常,在这里可以声明一个数组角标异常的对象,提示用户可能会产生的结果
		}*/
      //方法二:捕获异常,采用try...catch来进行捕获
		try{   //try的意思是尝试,这里就是先让它尝试的去运行
			System.out.println(a[index]);
		}catch(ArrayIndexOutOfBoundsException e){  //一旦出现了数组角标的异常,然后进行抓捕
			System.out.println(a[0]);  //这是对抓捕到的异常的一个处理。
		}
	}
}

现在来看一下两种方法对运行结果的差异:

通过结果可知,声明的异常还是会被抛出,而且一旦有一个位置出现问题,就会停止整个代码的运行,那么还是说,我们的问题并没有解决。那么如果进行捕获呢?

通过结果可以发现,进行捕获的异常,如果对捕获的异常进行了处理,那么是不会影响后面代码语句的执行的,除非遇到下一个没有被捕获的异常被强行停止,要么就是正常运行结束。

通过两个例子是说明捕获比声明好吗?显然并不是,我们发现,例子中处理的异常是在编译时没有报错的,而是在运行时可能会出错,这就是运行时异常。然后有些异常是我们不知道的,也不知道会有什么异常,其是异常的名字可以由我们自己去定义,然后进行声明。然而有些异常我们明知道不会出错,但是编译器在编译时提出可能会出现错误,这个时候我们首选声明,如:

File类是需要声明异常的类,尽管加上了判断该文件类是否存在,再决定是否创建该文件的语句,在编译时仍然报错,在这里就要进行声明或者捕获异常,而在这里向上声明比捕获要好,因为我们已经在创建这个文件了,尽管创建失败再运行一次即可,如果进行捕获还是要继续创建文件。注意,如果一个代码中声明的异常种类太多,我们可以直接声明一个它最大的父类。

上面的例子可以向上声明一个IOException解决:

因此,在进行异常的处理时,选择声明还是捕获要看具体的代码需求,以及分清他是编译时异常还是运行时异常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章