Java编程基础 ---- 异常

异常:
  就是不正常,程序在运行时出现的不正常情况,例如之前数组操作所提到的角标越界、空指针等异常。其实就是程序中出现的问题。这个问题按照面向对象思想进行描述,并封装成了对象。
  因为问题的产生有产生的原因、有问题的名称、有问题的描述等多个属性信息存在。当出现多属性信息最方便的方式就是将这些信息进行封装。异常就是java按照面向对象的思想将问题进行对象封装。这样就方便于操作问题以及处理问题。
  对这些问题进行分类。而且这些问题都有共性内容比如:每一个问题都有名称,同时还有问题描述的信息,问题出现的位置,所以可以不断的向上抽取。形成了异常体系:
--------java.lang.Throwable:
Throwable:可抛出的。
  |----Error:错误,一般情况下,不编写针对性的代码进行处理,通常是jvm发生的,需要对程序进行修正。
  |----Exception:异常,可以有针对性的处理方式
无论是错误还是异常,它们都有具体的子类体现每一个问题,它们的子类都有一个共性,就是都以父类名才作为子类的后缀名。

异常体系的特点:
异常体系中的所有类以及建立的对象都具备可抛性,也就是说可以被throw和throws关键字所操作(只有异常体系具备整个特点)。
throw和throws的用法:
  throw定义在函数内,用于抛出异常对象。
  throws定义在函数上,用于抛出异常类,可以抛出多个,用逗号隔开。
在开发时,如果定义功能时,发现该功能会出现一些问题,应该将问题在定义功能时标示出来,这样调用者就可以在使用这个功能的时候,预先给出处理方式。
如何标示呢?
  通过throws关键字完成,格式:throws 异常类名,异常类名…
这样标示后,调用者,在使用该功能时,就必须要处理,否则编译失败。
代码演示:抛出异常的方法

在这里插入图片描述
  当函数内有throw抛出异常对象,并未进行try处理,则必须要在函数上声明,否则编译失败(RuntimeException除外)。也就是说,函数内如果抛出RuntimeException异常,函数上可以不用声明。

需要声明的原因:是需要调用者对该异常进行处理。
如果函数声明了异常,调用者需要处理,处理方式可throws可try。
注:一般不会抛RuntimException异常。

异常分两种:
1、 编译时被检测异常:
  该异常在编译时,如果没有进行处理(没有throws也没有try),则会编译失败。
注:只要是Exception及其子类都是编译时被检测的异常。
2、运行时异常(编译时不检测):
  在编译时,不需要处理,编译器也不检查。该异常发生,建议不处理,让该程序停止,需要对代码进行修正。其中Exception有一个特殊的子类RuntimeException,以及RuntimeException的子类是运行异常,也就说这个异常是编译时不被检查的异常。
  运行时异常如果在函数内被抛出,在函数上不需要声明。
不声明的原因:不需要调用者处理,运行时异常发生,已经无法再让程序继续运行,所以,不让调用处理的,直接让程序停止,由调用者对代码进行修正。

异常处理语句:
try {
  需要被检测的代码;
}
catch(异常类 变量名){
  异常处理代码;
}
fianlly{
  一定会执行的代码;
}

有三种结合格式:
1、try {}
catch() {}
2、try {}
finally {}
3、try {}
catch() {} finally {}
注:1、finally中定义的通常是关闭资源代码,应为资源必须释放;
2、在catch中若有System.exit(0); //系统退出(jvm结束), finally将读不到。
代码演示:
在这里插入图片描述
结果为:
在这里插入图片描述
获取异常信息的方式:通过catch处理
catch(Exception e) { //e用于接收try检测到的异常对象。
  System.out.println(“message:”+e.getMessage());//获取的是异常的信息。
  System.out.println(“toString:”+e.toString());//获取的是异常的名字+异常的信息。
  e.printStackTrace();//打印异常在堆栈中信息;异常名称+异常信息+异常的位置。
}

异常处理原则:功能抛出几个异常,功能调用如果进行try处理,需要与之对应的catch处理代码块,这样的处理有针对性,抛几个就处理几个。
注:try对应多个catch时,如果有父类的catch语句块,一定要放在下面。
定义异常处理时,什么时候定义try,什么时候定义throws呢?
  功能内部如果出现异常,如果内部可以处理,就用try;
  如果功能内部处理不了,就必须声明出来,让调用者处理。使用throws抛出,交给调用者处理。谁调用了这个功能谁就是调用者;

自定义异常:
  当开发时,项目中出现了java中没有定义过的问题时,这时就需要我们按照java异常建立思想,将程序中出现的特有问题进行对象的封装。这个异常,称为自定义异常。
  对于除法运算,0作为除数是不可以的。java中对这种问题用ArithmeticException类进行描述。对于这个功能,在我们项目中,除数除了不可以为0外,还不可以为负数。可是负数的部分java并没有针对描述。所以我们就需要自定义这个异常。

自定义异常的步骤:
1、定义一个子类继承Exception或RuntimeException,让该类具备可抛性(既可以使用throw和throws去调用此类)。
2、让该类具备操作异常的共性方法。
当要定义自定义异常的信息时,可以使用父类已经定义好的功能。将异常信息传递给父类的构造函数。
class MyException extends
  Exception{
    MyException(String Message){
    Super(message);
  }
}

例如,对除数为0和负数的情况自定义异常:

扫描二维码关注公众号,回复: 6783840 查看本文章

在这里插入图片描述
运行结果:
在这里插入图片描述<>
异常的好处:
1、可以将问题进行封装;
2、将正常流程代码和问题处理代码相分离,方便于阅读。

异常的处理原则:
处理方式有两种:try或者throws;
调用到抛出异常的功能时,抛出几个,就处理几个(一个try对应多个catch);多个catch,父类的catch放到最下面;
catch内,需要定义针对性的处理方式。不要简单地定义printStackTrace或者输出语句,也不要不写。

异常的转换思想:当出现的异常是调用者处理不了的,就需要将此异常转换为一个调用者可以处理的异常抛出。
try{
  throw new AException();
}
catch(AException e){
  throw e;
}
  如果异常处理不了,但并不属于该功能出现的异常。可以将异常转换后,再抛出和该功能相关的异常。
  或者异常可以处理,但需要将异常产生的和本功能相关的问题提供出去,让调用者知道,并处理。也可以将捕获异常处理后,转换新的异常抛出。
try{
   throw new AException();
}
catch(AException e){
//对AException处理
  throw new BException();
}

当异常出现后,在子父类进行覆盖时,有了一些新的特点:
1、当子类覆盖父类的方法时,如果父类的方法抛出了异常,那么子类的方法要么不抛出异常要么抛出父类异常或者该异常的子类,不能抛出其他异常。
2、如果父类或者接口中的方法没有抛出过异常,那么子类是不可以抛出异常的,如果子类的覆盖的方法中出现了异常,只能try不能throws。

注意:
如果这个异常子类无法处理,已经影响了子类方法的具体运算,这时可以在子类方法中,通过throw抛出RuntimeException异常或者其子类,这样,子类的方法上是不需要throws声明的。

throw单独存在时,下面不要定义语句,因为执行不到。

常见异常:
1、脚标越界异常(IndexOutOfBoundsException)包括数组、字符串;
2、类型转换异常:ClassCastException
3、空指针异常:NullPointerException
4、不支持操作异常;
异常要尽量避免,如果避免不了,需要预先给出处理方式。比如家庭备药,比如灭火器。

  本文章是基于张孝祥老师java基础课程总结,转载请注明。

猜你喜欢

转载自blog.csdn.net/weixin_39771344/article/details/91812703