Java基础系列之异常处理

6.1 finally块中的代码什么时候被执行 ?

try{}里有一个return语句,那么finally{}中的代码是否会被执行?什么时候被执行?

在Java语言的异常处理中,finally块的作用就是为了保证无论出现什么情况,finally块的代码一定会被执行。程序return意味着结束对当前函数的调用并跳出这个函数,因此任何语句只能在return之前(exit函数除外),因此finally块里的代码也是在return前执行的。

package org.base;

public class Test {
	public static int testFinally(){
		try {
			return 1;
		} catch (Exception e) {
			// TODO: handle exception
			return 0;
		} finally {
			System.out.println("execute Finally!");
		}
	}
	
	public static void main(String[] args) {
		int i = testFinally();
		System.out.println(i);
	}
}

运行结果:execute Finally!
     1

package org.base;

public class Test {
	public static int testFinally(){
		try {
			return 1;
		} catch (Exception e) {
			// TODO: handle exception
			return 0;
		} finally {
			System.out.println("execute Finally!");
			return 3;
		}
	}
	
	public static void main(String[] args) {
		int i = testFinally();
		System.out.println(i);
	}
}

运行结果:execute Finally!
     3
结果可以看出finally块中的return语句覆盖了其他函数的return语句。

package org.base;

public class Test {
	public static int testFinally1(){
		int result = 1;
		try {
			result = 2;
			return result;
		} catch (Exception e) {
			// TODO: handle exception
			return 0;
		} finally {
			result = 3;
			System.out.println("execute Finally1!");
		}
	}
	
	public static StringBuffer testFinally2(){
		StringBuffer sb = new StringBuffer("Hello");
		try {
			return sb;
		} catch (Exception e) {
			// TODO: handle exception
			return null;
		} finally {
			sb.append(" World!");
			System.out.println("execute Finally2!");
		}
	}
	
	public static void main(String[] args) {
		int result = testFinally1();
		System.out.println(result);
		StringBuffer s = testFinally2();
		System.out.println(s);
	}
}

运行结果:execute Finally1!
     2
     execute Finally2!
     Hello World!
程序在执行到return时会首先将返回值存储在一个指定的位置,其次去执行finally块,最后再返回。 testFinally1中调用return前,先把result的值1存储在一个指定的位置,然后在执行finally块中的代码,此时修改result的值不会影响返回结果。testFinally2中,调用return前首先把s存储到一个指定位置,由于s为引用类型,因此在finally块中修改s将会修改程序的返回结果。

出现在Java程序中的finally块是不是一定会被执行?
不一定会被执行。
1)当程序在进入try语句块之前就出现异常时,会直接结束。

package org.base;

public class Test {
	public static void testFinally(){
		int i = 5 / 0;
		try {
			System.out.println("try block");
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("catch block");
		} finally {
			System.out.println("finally block");
		}
	}
	public static void main(String[] args) {
		testFinally();
	}
}

2)程序在try块中强制退出不会执行finally块中的代码

package org.base;

public class Test {
	public static void testFinally(){
		try {
			System.out.println("try block");
			System.exit(0);
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("catch block");
		} finally {
			System.out.println("finally block");
		}
	}
	public static void main(String[] args) {
		testFinally();
	}
}

运行结果:try block

6.2 异常处理的原理是什么?

异常是指程序运行时所发生的非正常情况或错误,JVM就会将出现的错误表示一个异常并抛出。这个异常可以在catch程序块进行捕获,然后进行处理。异常处理的目的则是为了提高程序的安全性和鲁棒性。

Java语言把异常当作对象来处理,并定义了一个基类(java.lang.Throwable)作为所有异常的父类。Java API中,将异常类分为Error(错误)和Exception(异常)两大类。

能使用throw抛出的异常:Error、Throwable、Exception、RuntimeException等。

6.3 运行时异常和普通异常有什么区别?

Error和Exception拥有共同的父类Throwable。

Error表示程序在运行期间出现了非常严重的错误,并且该错误不可恢复,导致程序终止执行。运行时异常多是由逻辑错误导致的,属于应该解决的错误。OutOfMemoryError、ThreadDeath等都属于错误。

Exception属于可恢复的异常,是编译器可以捕捉到的。包含:检查异常(Checked Exception)和运行时异常(Runtime Exception)。

(1)检查异常
1)异常的发生不会导致程序出错,进行处理后可以继续执行后续的操作。例如:当连接数据库失败后,可以重新连接后进行后续操作。
2)程序依赖于不可靠的外部条件,例如系统IO。

(2)运行时异常
不同于检查异常,编译器没有强制进行捕获并处理。如果不对这种异常进行处理,当出现这种情况时,会由JVM来处理。Java中常见的异常:NullPointerException(空指针异常)、ClassCastException(类型转换异常)、ArrayIndexOutOfBoundException(数组越界异常)、ArrayStoreException(数组存储异常)、BufferOverflowException(缓冲区溢出异常)、ArithmeticException(算术异常)等。

出现运行时异常后,系统会把异常一直往上层抛出,直到遇到处理代码为止。 若没有处理块,则抛到最上层;如果是多线程就用Thread.run()方法抛出异常单线程用main()方法抛出异常。抛出之后,如果是线程,那么这个线程也就退出了。如果是主程序抛出的异常,那么整个程序也就退出了。要么是线程终止,要么是主程序终止。

使用异常处理注意的几个问题:

  1. Java异常处理用到了多态的概念,进行异常捕获时:先捕获子类,再捕获基类的异常信息。反之,子类的异常信息永远不会被执行。
		try {
			// access db code
		} catch (ClassCastException e1) {
			//deal with this exception
		} catch (Exception e2) {
			
		}
  1. 尽早抛出异常;
  2. 可以根据实际的需求自定义异常类,自定义异常类继承Exception即可;
  3. 异常不能处理就抛出。

问以下编译能否通过?

package org.base;

public class Test {
	public static void f() throws ArithmeticException{
		System.out.println();
	}
	
	public static void main(String[] args) {
		f();
	}
}

能。ArithmeticException属于运行时异常,编译器没有强制对其进行捕获并处理。但如果换成IOException后,由于IOException属于检查异常,编译器强制去捕获此类型的异常,不对异常处理会有编译错误。

package org.base;
import java.io.IOException;

public class Test {
	public static void f() throws IOException{
		System.out.println();
	}
	
	public static void main(String[] args) throws IOException {
		f();// 不抛出异常,编译错误
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值