JAVA异常机制

1、概述
  • 异常:是在运行时期发生的不正常情况。

  • 在java中用类的形式对不正常情况进行了描述和封装对象,描述不正常的情况的类,就称为异常类。

  • 以前是将正常流程代码和问题处理代码写在一起,现在将正常流程代码和问题处理代码分离。提高阅读性。

    • 早期代码

      if (time < 0) {
      	// 处理办法。
      	// 处理办法。 
      	// 处理办法。
      	return 1
      }
      if (time > 100000) {
      	// 处理办法。  
      	// 处理办法。
      	// 处理办法。
      	return 2
      }
      
    • 现在的代码

      if (time < 0) {
          //就代表着时间为负的情况,这个对象中会包含着问题的名称,信息,位置等信息。
          throw new FuTime();
      }
      if (time > 100000) {
      	throw new BigTime();
      }
      
  • 其实异常就是java通过面向对象的思想将问题封装成了对象.

  • 用异常类对其进行描述。不同的问题用不同的类进行具体的描述。 比如角标越界。空指针等等。

  • 问题很多,意味着描述的类也很多,将其共性进行向上抽取,形成了异常体系。

  • Throwable:无论是error,还是异常,问题,问题发生就应该可以抛出,让调用者知道并处理。该体系的特点就在于Throwable及其所有的子类都具有可抛性。可抛性到底指的是什么呢?怎么体现可抛性呢?其实是通过两个关键字来体现的。throws throw ,凡是可以被这两个关键字所操作的类和对象都具备可抛性.

    • 一般不可处理的。Error,特点:是由jvm抛出的严重性的问题。这种问题发生一般不针对性处理。直接修改程序
    • 可以处理的。Exception
2、异常的分类
  • 编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。 这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。这样的问题都可以针对性的处理。

    • 编译时被检测异常必须声明,否则编译不了,一般编译时在检查语法错误完成之后才检测异常是否有声明
  • 编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类。这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的而或者引发了内部状态的改变导致的。那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。

  • 所以自定义异常时,要么继承Exception。要么继承RuntimeException。

3、finally
  • try...catch...finally的格式变形

    • try catch finally

    • try catch(多个)当没有必要资源需要释放时,可以不用定义finally。

    • try finally 异常无法直接catch处理,但是资源需要关闭。

      void show() throws Exception {
      	try {
      		// 开启资源。
      		throw new Exception();
      	} finally {
      		// 关闭资源。
      	}
      }
      
  • 注意事项

    • 样例1:以下代码return的值是30

      int show() {
      
      	int a = 0;
      
      	try {
      		System.out.println(1 / 0);
      	} catch (Exception e) {
      		a = 30;
      		return a;
      	} finally {
      		a = 40;
      	}
      
      	return a;
      }
      
    • 样例2:以下代码return的值是40

      int show() {
      
      	int a = 0;
      
      	try {
      		System.out.println(1 / 0);
      	} catch (Exception e) {
      		a = 30;
      		return a;
      	} finally {
      		a = 40;
      		return a;
      	}
      
      	return a;
      }
      
    • 样例3:以下代码return中a[0]的值是40

      int[] show() {
      
      	int[] a = new int[4];
      
      	try {
      		System.out.println(1 / 0);
      	} catch (Exception e) {
      		a[0] = 30;
      		return a;
      	} finally {
      		a[0] = 40;
      	}
      	return a;
      }
      
    • 样例4:以下代码打印的值是40

      public class MainTest {
      
      	Integer a = 0;
      
      	public static void main(String[] args) {
      		System.out.println(new MainTest().show().a);
      	}
      
      	MainTest show() {
      
      		MainTest mainTest = new MainTest();
      
      		try {
      			System.out.println(1 / 0);
      		} catch (Exception e) {
      			mainTest.a = 30;
      			return mainTest;
      		} finally {
      			mainTest.a = 40;
      		}
      		return mainTest;
      	}
      }
      
    • 从上述例子中我们可以得出结论、

      • 在Exception中return后执行finally时,return的值就已经是固定下来不可以变的了,如例子一return的是一个基本类型,那么此时就相当于是return 30 而不是return a了,所以不管在finally中把a的值改成多少,最终的结果还是return 30;

      • 当return的是一个对象的时候,此时return的值其实也是固定了的,相当于是return了一个地址,若在finally中对该对象中的值进行了修改,return之后地址依然指向的是那一个对象,只不过对象里面的值自然也就跟着变了。

      • 若finally代码块中也有return语句,那么之前的return语句自然也就跟着失效,以finally代码块中的return为准。

4、异常注意事项
  • 子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类(可以不抛)。

    • 因为旧代码在try catch的时候,只能catch父类所指定抛的异常或者该异常的子类
  • 如果父类抛出多个异常,那么子类只能抛出父类异常的子集,或者抛的都是父类抛的某个异常中的子类(如父类直接抛Exception的话,那么子类的方法就能随便抛了,因为所有异常都是Exception的子类)。

  • 如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值