java异常处理

1.异常概述

在Java中,异常就是在程序运行时产生的错误,例如,向一个不存在的文本文件写入数据时,就会产FileNotFoundException异常(系统找不到指定文件)。接下来通过一个简单的实例认识一下另外一个异常ArithmeticException算数异常

以3除以0为例,在算数当初0是不能被除的,代码如下:

public class Demo{
	public static void main(String[] args) {
		int i = 3/0;
		System.out.println(i);
	}
}

返回结果:

111111111

从返回结果可以看出,产生了算术异常ArithmeticException,导致算术异常的根源在于算术表达式3/0中,0作为除数出现,所以正在执行的程序被中断(第3行以后,包括第3行的代码都不会执行)。

FileNotFoundException异常和ArithmeticException异常外,Java中还有许许多多的异常,如空指针异常数组元素下标越界异常等等,由于Java是一门面向对象的编程语言,所以在Java中,把上述异常都被称为异常对象,当程序执行到某一方法处产生异常时,java虚拟机(JVM)就会产生与已产生的异常相匹配的异常对象,如果没有异常对象做异常处理,那么久会显示上图所示的异常信息

2.捕捉处理异常

try-catch代码块主要用于捕捉并处理异常,实际应用时,改代码块还有一个可选的finally代码块。try-catch-finally的语法如下:
 

try {
			//程序代码块
		}catch(ArithmeticException e ) {
			//对ArithmeticException异常处理
		}finally {
			//代码块
		}
  • try中的程序代码块指的是可能产生异常的代码;
  • catch中的对ArithmeticException的处理的作用是捕捉并处理与已产生的异常类型相匹配的异常对象e;
  • finally中的代码块是异常处理过程中最后被执行的部分,无论程序是否产生异常,finally中的代码块都被执行,实际应用时,finally中通常放置一些释放资源、关闭对象的代码;

通过try-catch-finally的语法可知,捕捉处理异常分为try-catch代码块finally代码块两部分组成,下面分别予以介绍。

2.1try-catch代码块

把可能产生异常的代码放在try中,把处理异常对象e的代码放在catch中,接下来通过上面讲的实例演示一下try-catch代码块,代码如下:

public class Demo{
	public static void main(String[] args) {
		try {
			int i = 3/0;
		}catch(ArithmeticException e ) { 			//对ArithmeticException异常捕捉
			e.printStackTrace();					//打印异常
			System.out.println("算术发现异常,请检查");	//对发现的异常做处理
		}
		System.out.println("程序执行完毕");
	}
}

返回结果:

从返回结果看出,程序仍然输出最后的提示信息程序执行完毕,这说明程序的执行没有因为产生异常被中断,由此可知,使用try-catch代码块捕捉并处理异常,不会因为产生异常影响程序的执行。

在catch代码块中使用了ArithmeticException对象的printStackTrace()方法输出了异常信息,除此之外,ArithmeticException对象还提供了其他的方法用于获取异常的相关信息。

  • getMessage()方法:获取有关异常事件的信息;
  • toString()方法:获取异常的类型与性质;

注意:ArithmeticException是try代码块传递给catch代码块的异常类型,e是与已产生的异常类型相匹配的异常对象

在上面例子中,try代码块后面用了一个catch代码块来捕捉异常,但是如果遇到需要处理多种异常信息的情况时,可以在一个try代码块后面跟多个catch代码块,这里需要注意的是,如果使用了多个catch代码块则catch代码块中的异常类顺序是先子类后父类

多个catch语法如下:

try {
			//程序代码块
		}catch() {
			//异常处理
		}catch() {
			//异常处理
		}catch() {
			//异常处理
		}
        ............

下面我们来捕捉两个异常,一个数组元素下标越界异常和空指针异常,ArrayIndexOutOfBoundsException(数组下标越界异常)NullPointerException(空指针异常),代码如下:

public class Demo{
	public static void main(String[] args) {
		try {
			//创建一个空对象
			Object a = null;
			//创建一个数组下标为2
			int i[] = new int[2];
			//输出空对象
			a.hashCode();
			//输出数组下标为3
			System.out.println(i[3]);
			//数组越界异常
		}catch(ArrayIndexOutOfBoundsException e ) {
			System.out.println("发现异常:数组下标越界");
			//数组空指针异常
		}catch(NullPointerException e ) {
			System.out.println("发现异常:空指针");
		}
	}
}

如果我们把Exception异常放在空指针和数组下标异常前面呢?看下图:

因为Exception是ArrayIndexOutOfBoundsException(数组下标越界异常)NullPointerException(空指针异常)他俩的父类,如果try代码块中有多个catch代码块顺序应该先子类后父类,所以把父类放在子类就会报错

2.2finally代码块

完整的异常处理语句应该包含finally代码块,通常情况下,无论程序中有无异常产生,finally代码块中的代码都会被执行。、

续上面的例子,代码如下:

public class Demo{
	public static void main(String[] args) {
		try {
			//创建一个空对象
			Object a = null;
			//创建一个数组下标为2
			int i[] = new int[2];
			//输出空对象
			a.hashCode();
			//输出数组下标为3
			//System.out.println(i[3]);
			//数组越界异常
		}catch(ArrayIndexOutOfBoundsException e ) {
			System.out.println("发现异常:数组下标越界");
			//数组空指针异常
		}catch(NullPointerException e ) {
			System.out.println("发现异常:空指针");
		}finally{
			System.out.println("控制台关闭");
		}
	}
}

返回结果:

从返回结果看出,程序在捕捉完异常信息之后,会执行finally代码块中的代码,另外,在以下三种特殊情况下,finally块不会被执行,如下:

  • 在finally代码块中产生异常;
  • 在前面的代码中使用了System.exit()退出程序;
  • 程序所在的线程死亡;

3.在方法中抛出异常

如果某个方法可能会产生异常,但不想在当前方法中处理这个异常,则可以使用throws关键字throw关键字在方法中抛出异常。

3.1throws关键字

throws关键字常被应用于方法上,表示方法可能抛出异常,当方法抛出多个异常时,可用逗号分隔异常类型名,使用throws关键字抛出异常的语法如下:

返回值类型名 方法名(参数表)throws 异常类型名{     }

下面例子中演示throws用法,代码如下:

public class Demo{
	public void sum() throws ArithmeticException{   //使用throws关键字抛出ArithmeticException算术异常
		int i = 3/0;
		System.out.println(i);
	}
	
	public static void main(String[] args) {
		Demo a = new Demo();		//创建对象
		try {
			a.sum();				//输出对象方法
		}catch(ArithmeticException e) {		//对接受的异常做处理
			System.out.println("算术发现异常,请检查");
		}finally{
			System.out.println("控制台关闭");
		}		
	}
}

说明:使用throws关键字将方法产生的异常抛给上一级后,如果上一级不想处理该异常,那么可以继续向上抛出,但最终要有能够捕捉并处理这个异常的代码

3.2throw关键字

throw关键字虽然可以用于抛出Exception类中的子类异常,但更重要的用于是抛出自定义异常使用throw关键字抛出异常的语法如下:

throw new 异常类型名(异常信息)

创建自定义异常,代码如下:

public class Demo{
	public static void main(String[] args) {
		int b = 0;
		if(b == 0) {
			//创建自定义异常
			throw new ArithmeticException("b不能等于0");
		}
	}
}

返回结果:

3.3throws关键字和throw关键字的区别

throws关键字和throw关键字的区别如下:

  • throws用在方法声明后面,表示抛出异常,由方法的调用者处理,而throw用在方法体内,用来制造一个异常,由方法体内的语句处理;
  • throws是声明这个方法会抛出这种类型的异常,以便使它的调用者知道要捕捉这个异常,而throw是直接抛出一个异常实例;
  • throws表示出现异常的一种可能性,并不一定会产生这些异常,但如果使用throw,就一定会产生某种异常;

4.异常的使用原则

异常处理的主要作用是捕捉并处理程序在运行时产的异常,编写代码处理某个方法可能出现的异常时,可遵循以下原则:

  • 不要过度使用异常,虽然通过异常可以增强程序的健壮性,但使用过多不必要的异常处理,可能会影响程序的执行效率;
  • 不要使用过于庞大的try-catch块,在一个try块中放置大量的代码,这种写法看上去“很简单”,但是由于try块中的代码过于庞大,业务过于复杂,会增加try块中出现异常的几率,从而增加分析产生异常原因的难度;
  • 避免使用catch(Exception e),如果所有异常都采用相同的处理方式,那么将会导致无法对不同异常进行分类处理;
  • 不要忽略捕捉的异常,遇到异常一定要及时处理;
  • 如果父类抛出多个异常,则覆盖方法必须抛出相同的异常或其异常的子类,不能抛出新异常;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值