Java核心基础之容易被忽视的细节问题——异常处理


1、在try块中声明的变量是局部变量,在catch、finally、以及异常处理外都不能被访问。所以我们要把InputStream/OutputStream一类的变量声明在try块外,以方便在finally块中关闭连接。

2、当try块中出现异常时,JVM会生成一个类型最合适的异常对象记录异常信息,再通过instanceof关键字与catch块声明的异常类型逐个比较寻求捕获。如果异常没有被捕获,就抛出异常,程序停止运行。

3、进行异常捕获时要先捕获小异常,再捕获大异常,即先捕获子异常类再捕获父异常类。

4、Java7中定义可在一个catch中捕获多种异常,形如:
try{
……;
}catch(IndexOutOfBoundsException | NumberFormatException ex){
……;
}

但是请注意,当使用捕获多异常时,ex变量就被隐式声明为final类型,不能被修改;而捕获单异常时,异常变量就不是final类型,可以被修改。

5、finally块只有在以下情况不会执行:
(1)在try块或catch块中调用System.exit(1);
(2)CPU出现异常被关闭;
(3)执行finally块所在线程阻塞或死亡;
(4)finally块中抛出异常并未被捕获,则finally块不会被执行完毕。

6、try-catch-finally的return问题
当try块中return的时候,
a、要么在catch块中return;
b、要么在异常处理外return;
c、要么在finally块中return;
为保证捕获异常后也能有返回值返回,a、b、c三种情况至少存在一种,否则编译出错。且a、b两种情况不能同时存在,效果相同,都是在捕获异常后return。当情况c存在时,其他的返回值均失效,一定返回finally块中的返回值。

7、throws与throw区别
throws是声明抛出异常,由JVM去自动处理异常,打印异常栈信息,终止程序运行。需要注意的是,throws只能写在方法签名之后,且子类只能声明抛出比父类范围相等或更小的异常(即子异常类)。
throw是主动抛出异常的方式,更加灵活。需要注意的是,当显示抛出异常时,要么需要try-catch处理,要么需要throws显式声明抛出异常。

8、Check异常与Runtime异常区别
Check异常是编译期会检查的异常,必须捕获或声明抛出才能通过编译,体现了Java的设计思想,要求严谨性,但许多Check异常我们只是显式的抛出并不知道如何处理。
Runtime异常在编译期不会被检查,但是仍然可以通过try-catch捕获,所以具有更大的灵活性。

9、项目中如何正确使用异常
(1)使用try-catch-finally结构捕获相关异常。
(2)在catch中捕获相关异常,将相关异常信息提供给管理员,并throw适应用户的自定义异常。
示例如下:
//自定义异常类,如果想要自定义运行时异常,请继承RuntimeException类
public class MyException extends Exception{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public MyException(){
		
	}
	
	public MyException(String msg){
		super(msg);
	}
}
//场景测试类
public class ActionTest {
	//初始值
	private double initPrice = 30.0;
	
	//竞价方法,提出竞价
	public void bid(String bidPrice) throws MyException{
		
		double d = 0.0;
		try{
			d = Double.parseDouble(bidPrice);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new MyException("竞价必须数值,不能包含其它字符!");
		}
		if(d <= initPrice){
			throw new MyException("竞价必须大于初始值!");
		}
		initPrice = d;
	}
	
	//测试
	public static void main(String[] args){
		ActionTest action = new ActionTest();
		try {
			action.bid("abc");
		} catch (MyException e) {
			System.err.println(e.getMessage());
		}
	}
}
Java核心基础之容易被忽视的细节问题——异常处理_第1张图片

这样就向用户屏蔽了底层异常。

其他方面:
(1)不依赖异常,一些完全可以预知且处理逻辑清晰的错误尽量不使用异常处理。
(2)捕获异常后要进行对应的处理,而不仅仅是输出异常信息。
(3)try块要尽力精简。

你可能感兴趣的:(Java)