Java:异常

本文详细讲解了异常处理的概念,通过示例展示了try-catch的运用,讨论了异常之间的继承关系,并强调了在代码中处理常见和特殊异常的技巧。学习如何正确处理OpenException、CloseException和FindException,以及在继承场景下的异常管理策略。

异常概念

当你不确定一段代码会不会抛出异常时,可以用try把这段代码包起来,用catch区分抛出的宜昌的类型执行对应的操作
在这里插入图片描述
通过异常机制,我们可以把异常处理和业务逻辑分离开来,不用使用if-else多重嵌套来折磨自己了。

异常处理运行实例

public class test{
	public static void f()
	{
		int[] a = new int[10];
		a[10] = 10;		//返回一个ArrayIndexOutOfBoundsException异常
		System.out.println("hello_f");
	}
	
	public static void g() {
		f();
	}
	
	public static void h() {
		int i=10;
		if(i<100) {
			g();
		}
	}
	
	public static void k() {
		try {
			h();
		}
		catch(NullPointerException e){
			System.out.println("null");
		}
		catch(ArrayIndexOutOfBoundsException e){
			System.out.println("hello_k");
			throw e;		//throw是将异常抛出去,如果没有这一句main中的catch不会被执行
		}
	}
	
    public static void main(String[] args) {
    	try {
    		k();
    	}
    	catch(ArrayIndexOutOfBoundsException e) {
    		System.out.println("caught");
    		System.out.println(e.getMessage());	 //异常发生时放在异常里面的值【10】
    		System.out.println(e);				//等于e.toString()
    		System.out.println("main");
    		e.printStackTrace();				//e.toString的值+异常发生位置
    	}
    }
}

结果:

hello_k
caught
Index 10 out of bounds for length 10
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
main
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
	at test.test.f(test.java:7)
	at test.test.g(test.java:12)
	at test.test.h(test.java:18)
	at test.test.k(test.java:24)
	at test.test.main(test.java:37)

将"throw e"注释掉的结果:

hello_k

以下是上述代码的命令执行顺序图
请添加图片描述
在这里插入图片描述

异常之间的关系

class FindException extends Throwable{}
class OpenException extends Exception{}//Exception继承自Throwable,其它异常类继承自Exception
class CloseException extends OpenException{}	//不合理!

public class test{
	
	public static int open() {
//		int[] a = new int[10];	//*当取消注释后a[10]=10会直接抛出异常ArrayIndexOutOfBounds,
//		a[10] = 10;			//*同时跳过后面的语句[return -1]
		return -1;
	}
											//为以后可能会抛出的异常做准备
	public static void readFile() throws OpenException, CloseException, FindException {
		if( open() == -1) {			//*取消注释后不会判断open的返回值是否等于-1,
			throw new  CloseException();	//*而是处理a[10]抛出的异常:
		}	//*将ArrayIndexOutOfBounds返回给调用函数,同时throw这一句也不会执行
	}
	
    public static void main(String[] args) {
    	try {
			readFile();					//函数中所有可能抛出的异常都必须有对应的语句
		} 								//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    	catch (CloseException e) {	//Close必须在Open的前面,因为Close继承自Open,所以如果
			System.out.println("Close");//Close在Open下面,就会执行Open对应的catch语句,
		}								//所以Close永远无法到达。	
    	catch (OpenException e) {
    		System.out.println("Open");
		} 
    	catch (FindException e) {
    		System.out.println("Find");
		}
    	catch(Exception e) {
    		System.out.println("Anyaway");	//*因为没有对ArrayIndexOutOfBounds的catch
    	} 									//*所以使用Exception来处理
    	
    }
}

结果:

Find

取消了注释的结果:

Anyaway

像a[10] = 10这样的运算不用try-catch是因为这些错误太常见了,如果要对应处理,代码会非常庞大。

异常遇到继承

class FindException extends Throwable{}

class OpenException extends Exception{}

class CloseException extends OpenException{}

class ArrayIndex{
	public ArrayIndex() throws OpenException{}	/*构造函数抛出异常不好*/
	public void f() throws OpenException{}
	public static void main(String[] args) {}
}

/*如果允许子类的成员抛出超出父类范围的异常,那么代码中父类的成员
		不知道如何处理子类抛出的父类没有的异常类型*/
public class test extends ArrayIndex{  //子类的构造函数可以抛出和超出父类异常范围的异常类型
	public test() throws OpenException, FindException {	
		super();	//当父类的构造函数抛出异常时(这不好),子类的构造函数必须也抛出相应异常,
					//而默认的构造函数不会抛出异常,所以要手动添加构造函数
	}	
	//定义子类的对象时,对象无从得知父类的构造会抛出什么异常,所以子类的构造必须抛出父类抛出的异常
	public void f() throws OpenException{}	//成员不可以抛出比父类多的异常
    public static void main(String[] args) {//可以抛出比父类少的异常或不抛异常
     	try {
    		ArrayIndex p = new test();	//父类中存子类的数据:向下造型
			p.f();
		} catch (OpenException e) {
			e.printStackTrace();
		} catch (FindException e) {
			e.printStackTrace();
		}
    }
}

当覆盖一个函数的时候,子类不能声明抛出比父类的版本更多的异常
在子类的构造函数中,必须声明父类可能抛出的全部异常

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值