一、什么是异常?

异常:就是不正常 程序在运行的过程,出现了一些突发状况,造成程序无法继续运行。我们把上述的突发状况,无法正常运行的这些状态称为Java中的异常。 Java中的异常:就是程序中出现的错误(bug),或者不正常现象

异常的产生过程解析

1)定义一个类ExceptionDemo;
2)定义一个主方法,在主方法中定义一个int类型的数组,在这个数组中存放int类型的数据;
3)在这个类中自定义一个函数getValue,在这个函数中根据调用者传递过来的下标和数组返回给调用者
对应的数据;
4)在主方法中调用自定义函数getValue,接收自定义函数返回回来的数据,并将数据打印到屏幕上;
image.png
说明:上述代码发生异常的过程是如何调试的
1)jvm先去调用main函数,在main函数中调用了getValue函数,然后jvm将getValue函数加载到内存中;
2)Jvm在执行getValue函数的时候,由于数组下标index的值3超过了数组的最大下标的范围,所以在这里发生了异常问题,ArrayIndexOutOfBoundsException(数组越界),这样导致程序就不会向下执行,jvm会在发生异常的地方停止,jvm会将发生异常信息(发生异常的位置、异常内容、异常类型等)封装到一个类中(Java的异常类),然后把这个封装了异常信息类的对象(new 异常类)丢给了当前调用函数的地方。
3)如果发生异常,jvm会自动创建封装了异常信息的异常类的对象,然后将对象使用throw关键字抛给调用getValue函数的地方。
4)由于getValue函数把问题抛给了main函数,所以导致了main函数中也有了异常,而main函数中的异常是被迫接收的,此时main函数中并没有解决此异常的解决方案,但是main函数是jvm调用的,所以main函数又将异常抛给了jvm虚拟机,jvm已经是底层了,不能再将异常抛出,jvm需要对这个问题进行处理,即将这个问题显示到屏幕上,让程序的使用者看到。

  1. /*
  2. 针对发生的异常进行简单的处理
  3. */
  4. class ExceptionDemo1
  5. {
  6. public static void main(String[] args)
  7. {
  8. //定义数组
  9. int[] arr={1,2,5};
  10. //int value=getValue(arr,1);
  11. int value=getValue(arr,1);
  12. System.out.println(value);
  13. }
  14. //定义函数根据指定的下标返回对应的值
  15. public static int getValue(int[] arr,int index)
  16. {
  17. /*
  18. 以后在开发中,定义函数的时候,对外界传递过来的参数一定要
  19. 合法性的判断
  20. 这里需要对错误数据进行判断,然后将错误信息报告给调用者
  21. 在实际开发中我们一般会给固定的文件写错误信息(错误文档)
  22. */
  23. //System.out.println("haha");
  24. /*
  25. * 发生空指针异常的地方,一定是使用了某个引用变量,而这个引用变量又不指向任何的对象
  26. * 也就是说引用变量中保存的是null。这是使用空的引用调用属性或行为,而由于根本引用不指向
  27. * 任何的对象,那么就没有属性和行为而言,更无法去调用了。肯定就发生空指针异常。
  28. */
  29. if(arr==null)
  30. {
  31. throw new NullPointerException("对不起,数组引用变量的值不能为null");
  32. }
  33. if(index<0 || index>=arr.length)
  34. {
  35. throw new ArrayIndexOutOfBoundsException("下标越界了。。。");
  36. }
  37. return arr[index];
  38. }
  39. }

异常的体系

Throwable体系:

  • Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。 在程序运行时,会产生一些错误信息。java把这些错误信息使用Error或其子类进行描述。 错误属于系统级别的,是由于JVM在操作内存时(JVM需要借助操作系统来实现内存的操作),出现了一些不正常的操作,造成内存错误,出现错误后操作系统就会把这个错误返回给JVM。在程序中,遇到错误时,java没有针对性的解决方案,只能通过修改源代码的方式来解决程序中的错误问题。
  • Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒。在程序运行时,也会出现一些异常状况。表示Java程序中存在的异常问题,而不是错误问题。这些异常问题,在程序中通过判断等形式是可以检测并且预防的。针对这些异常问题,程序员在写代码的时候一旦发生,必须给出有效的解决方案。java对于异常状况是有针对性的解决方案(异常处理),例:角标越界、空指针异常等。异常状况的发生,通常是JVM在操作一些数据时,出现的问题,java对于异常的发生,是可以通过一些手段(捕获)避免程序终止运行,保证让程序继续向下正常执行。

异常分类

  • 编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)
  • 运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会让编译器检测(不报错)。

    二、异常问题怎么去解决和处理:

    Java异常处理的五个关键字:try、catch、finally、throw、throws

抛出异常throw

  1. throw new 异常类名(参数);
  2. throw new NullPointerException("要访问的arr数组不存在");
  3. throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");

声明异常throws

声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。

  1. 修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2
  2. {
  3. 方法体
  4. }

捕获异常try…catch

在开发中,main函数中不会出现声明,在main函数通常是使用捕获。

  1. try{
  2. 编写可能会出现异常的代码
  3. }catch(异常类型 对象名){
  4. 处理异常的代码
  5. //记录日志/打印异常信息/继续抛出异常
  6. }

try:该代码块中编写可能产生异常的代码。 catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。

注意:try和catch都不能单独使用,必须连用。

获取异常信息

方法 说明
getMessage() 获取报错原因.获取异常的描述信息,原因(提示给用户的时候,就提示错误原因)。
toString() 获取报错的类型和原因
printStackTrace() 直接打印报错的类型、原因和位置.包含了异常的类型,异常的原因,还包括异常出现的位置.

捕获多个异常

多个异常一次捕获,多次处理。

  1. try{
  2. 编写可能会出现异常的代码
  3. }catch(异常类型A e){ try中出现A类型异常,就用该catch来捕获.
  4. 处理异常的代码
  5. //记录日志/打印异常信息/继续抛出异常
  6. }catch(异常类型B e){ try中出现B类型异常,就用该catch来捕获.
  7. 处理异常的代码
  8. //记录日志/打印异常信息/继续抛出异常
  9. }

三、finally 代码块

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

try…catch….finally:自身需要处理异常,最终还得关闭资源。

  1. try{
  2. 可能发生异常的代码
  3. }catch(异常类名 变量名){
  4. 处理异常的代码。
  5. }finally{
  6. 程序中永远都能执行到的代码
  7. }

四、自定义异常

什么是自定义异常类?

自定义一个业务逻辑异常:xxxException

异常类如何定义?

  1. 自定义一个编译期异常: 自定义类 并继承于java.lang.Exception。
  2. 自定义一个运行时期的异常类:自定义类 并继承于java.lang.RuntimeException。
  1. public class 异常类的名字 extends Exception / RuntimeException
  2. {
  3. //不需要任何的属性和行为,仅仅只需要提供构造函数即可。
  4. public 异常类的名字(){}
  5. public 异常类的名字( String message ){
  6. super(message);
  7. }
  8. }

不需要任何的属性和行为,仅仅只需要提供构造函数即可

查看异常源码

  1. public class NullPointerException extends RuntimeException {
  2. //版本号 没什么用
  3. private static final long serialVersionUID = 5162710183389028792L;
  4. //构造方法
  5. public NullPointerException() {
  6. super();
  7. }
  8. //构造方法
  9. public NullPointerException(String s) {
  10. super(s);
  11. }
  12. }