(15)Java中的异常

异常

异常所带来的一个相当明显的好处是,它能降低错误代码处理的复杂度。

最大的异常是Throwable,异常可分为可修复异常(Exception)和不可修复异常(Error)

Exception:程序本身及环境

Error:内部系统,堆内存溢出错误,引用不释放,会造成内存泄露问题

对于程序中的问题有三种

  1. 编译期异常
  2. 运行时异常
  3. 逻辑异常

常用的异常

	RuntimeException 运行时的异常
	NullPointerException 空指针异常
	ArithmeticException  算术运算异常
	ArrayIndexOutofBoundsException 数组下标越界异常
	ClassCastException  类型转换异常
	FileNotFoundException  文件找不到异常
	IOException  IO异常

异常处理程序

	try {
		// 可能产生异常的代码
	} catch (Type1 id1) {
		// 异常信息1
	} catch (Type2 id2) {
		// 异常信息2
	} catch (Type3 id3) {
		// 异常信息3
	} finally {
		//总会被执行的代码
	}
	
	异常的级别:异常1 < 异常2 < 异常3

异常处理理论上有两种基本模式:

  1. Java支持终止模式。在这种模式中,一旦异常被抛出,就表明错误已无法挽回,也不能回来继续执行。
  2. 恢复模式:意思是异常处理程序的工作是修正错误,然后重新尝试调用出问题的方法,并认为第二次成功。(把try放在while循环中,这样就可以不断进入try)

恢复模式:开始显得很吸引人,但是不实用,其中主要的原因可能是它所导致的耦合:恢复性的处理程序需要了解异常抛出的地点,这这势必要包含依赖抛出位置的非通用性代码,增加了代码编写和维护困难。

自定义异常

自己定义异常类,必须从已有的异常类继承

public class SimpleException extends Exception {
	public SimpleException(String message) {
    	super(message);
    	System.out.println(message);
	}
}

public class InheritingException {
	public void f() throws  SimpleException{
    	System.out.println("Throw SimpleException from f()");
    	throw new SimpleException("没错,这就是我自己定义的一个简单的异常");
		}
	public static void main(String[] args) {
    	InheritingException in = new InheritingException();
    	try {
        	in.f();
    	}catch (SimpleException s){
        	System.out.println("这个简单的异常被我抓住了");
    	}
	}
}

重新抛出异常:

把异常抛给上一级环境中的异常的异常处理程序,同一个try块的后续catch子句将被忽略。

异常链:

在捕获一个异常后抛出另外一个异常,并且希望把原始的信息保存下来,这就被称为异常链

	public classIOException extends Exception{
    	//定义异常的原因
    	publicIOException(String message){
    		super(message);
    	}
    	//定义异常原因,并携带原始的异常
    	publicIOException(String message,Throwable cause){
    		super(message,cause);
    	}
    	//保留原始异常信息
   		publicIOExcepiton(Throwable cause){
   			super(cause);
    	}
	}

finally

对于没有垃圾回收和析构函数自动调用机制的语言来说,finally他能保证,无论try块里面发生什么,内存总能得到释放

finally主要用在:已经打开的文件或者网络连接,在屏幕上画的图形,甚至是外部世界的某个开关

无论finally是否可以和break,continue,return使用,仍然会执行

有以下五种特殊情况下,finally块不会被执行:
1. 在finally语句块中发生了异常
2. 在前面的代码中使用了System.exit(0)退出程序。这个System.exit(0)代码是终止Java虚拟机的运行,即退出结束当前的程序。
3. 程序所在的线程死亡。
4. 关闭CPU。
5. 如果一个方法内在执行try{}语句之前就已经return了。只有与 finally 相对应的 try 语句块得到执行的情况下,finally 语句块才会执行。

Java异常类层次结构图
在这里插入图片描述

例题:finally在return之前执行还是在return之后执行?:在return中间执行。

		public class Test {
			public static void main(String[] args) {
				System.out.println(Test.method());
			}
			public static int method(){
				try {
					return 1;
				} catch (Exception e) {
					return 0;
				} finally {
					return 2;
				}
			}
		}
		//执行结果
		2

结论:
1.执行过程:这里仅仅需要注意的是在try{}语句中执行到return 1 会在临时栈中存储值为1的变量。接着回去执行finally里面的内容,这时执行finally中的return 2;方法,这时临时栈中的值就是变为 2,会覆盖原来临时栈中的值1.所以它的返回值为2。

2.finally 语句块在 try 语句块中的 return 语句之前执行。3.finally 语句块在 catch 语句块中的 return 语句之前执行。

异常的使用指南

使用异常的情况

  1. 在恰当的级别处理问题
  2. 解决问题并重新调用产生异常的方法
  3. 进行少许修补,然后绕过异常发生的地方继续执行
  4. 用别的数据进行计算,以代替方法预计会返回的值
  5. 把当前运行环境下能做的事情尽量做完,然后把相同(不相同)的异常重抛到更高层
  6. 终止程序
  7. 进行简化
  8. 让类库和程序更安全

下一章,(16)Java中的内部类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值