Java 异常

109 阅读5分钟

1. 异常概述

1.1 异常概念

异常,就是不正常的意思。指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。

在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象

Java处理异常的方式是中断处理

异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行。

1.2 异常体系

异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Errorjava.lang.Exception ,平常所说的异常指 java.lang.Exception

image.png

  • Error:严重错误Error,无法通过处理的错误,只能事先避免。
  • Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。

1.3 异常分类

异常分类:根据在编译时期还是运行时期去检查异常

  1. 编译时期异常checked异常必检异常,必须处理。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)。提醒程序员检查本地信息
  2. 运行时期异常runtime异常免检异常,不强制要求编写代码捕获或声明异常。在运行时期,检查异常。在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)。代码出错而导致程序出现的问题。一般是由于参数传递错误带来的问题

1.4 异常的作用

  1. 作用一:异常用来查询Bug关键参考信息。
  2. 作用二:异常可以作为方法内部一种特殊的返回值,以便通知调用者底层的执行情况。而不是直接打印在控制台上。

2. 异常的处理方式

异常处理的方式:JVM 默认的处理方式自己处理抛出异常

2.1 JVM 默认的处理方式

把异常名称、异常原因及异常出现的位置等信息输出在控制台

程序停止运行,下面代码不会再执行了

2.2 自己处理(捕获异常)

目的:当代码遇到异常时,可以让程序继续往下执行。

try{
     //编写可能会出现异常的代码
}catch(异常类型  e){
     //处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}
int[] arr = {1,2,3,4};
try{
    //可能出现异常的代码。
    sout(arr[10]);
    }catch (ArrayIndexOutOfBoundsException e){
        sout("索引越界了");
    }
    sout("111111111");
}

上述代码第4行处会出现异常:

  1. 程序会在这里创建一个 ArrayIndexOutOfBoundsException 对象,new ArrayIndexOutOfBoundsException()
  2. 拿着这个对象到catch小括号中对比,看括号中的变量是否可以接受这个对象。
  3. 如能被接受,就表示该异常被捕获,执行catch里代码。
  4. 当catch里面所有代码执行完毕,继续执行try...catch体系下其他代码。

关于try...catch的几个问题:

  • 如果try中没有遇到问题,怎么执行?

    try中全部执行,catch中不会执行。

  • 如果try中遇到多个问题,怎么执行?

    只会运行下述代码第3行,不会运行第4行。

    多个异常,必须写多个catch与之对应。

    如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定写在下面

    int[] arr = {1,2,3,4};
    try{
        sout(arr[10]);//ArrayIndexOutOfBoundsException 
        sout(2/0);//ArithmeticException
        }catch (ArrayIndexOutOfBoundsException e){
            sout("索引越界了");
        }
        sout("111111111");
    }
    
    //jdk7 可以处理多个异常
    catch (ArrayIndexOutOfBoundsException | ArithmeticException e)
    
  • 如果try中遇到问题没有被捕获,怎么执行?

    相当于try...catch代码白写了,交给虚拟机处理,运行停止。

  • 如果try中遇到了问题,那么try下面其他代码还会执行吗?

    遇到问题下面代码不会执行了,直接跳转到catch。

2.3 抛出异常

throws:写在方法定义处,表示声明一个异常,告诉调用者,使用本方法可能会有哪些异常。

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

编译时异常:必须写

运行时异常:可以不写

throw: 写在方法内,结束方法,手动抛出异常对象,交给调用者,方法中下面代码不再执行。

public static void main(String[] args) {

    int[] arr = null;
    int max = 0;
    
    //为了使代码继续向下运行try...catch
    try {
        max = getMax(arr);
    } catch (NullPointerException e) {
        e.printStackTrace();
    }
    
}

public static int getMax(int[] arr){

    if(arr == null){
        throw new NullPointerException();
    }
    
    //下面代码不会再执行
    int max = arr[0];
    for (int i = 0; i < arr.length - 1; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

3. 异常中的常见方法

Throwable类中定义了一些查看方法:

  • public String getMessage():获取异常的描述信息,原因(提示给用户的时候,就提示错误原因)。
  • public String toString():获取异常的类型和异常描述信息(不用)。
  • public void printStackTrace():打印异常的跟踪栈信息并输出到控制台。仅仅打印信息,不会停止运行。红色字体打印,信息最全。(常用)

  注:打印错误的信息,System.err.println(123),红色字体。

4. 自定义异常

目的:提供更灵活、更具体的错误处理机制。

// 业务逻辑异常
public class LoginException extends Exception {
    /**
     * 空参构造
     */
    public LoginException() {
    }

    /**
     *
     * @param message 异常信息
     */
    public LoginException(String message) {
        super(message);
    }
}

 throw new LoginException( name + "已经存在了");

注:避免过渡设计