Version: Next

异常

异常的概念

异常指在方法態按照正常方式完成时,可以通过抛出异常的方式退出该方法,在异常中封装了执行过程中的错误信息和原因,调用方在获取该异常后可根据业务的情况选择处理该异常或者继续抛出异常

方法在执行过程中出现异常时,Java异常处理机制会将代码的执行权交给异常处理器,异常处理器根据在系统中定义的异常处理规则执行不同的处理逻辑(抛出或捕获异常并处理)

异常分类

image-20200618231944040

在Java中,Throwable是所有错误或异常的父类

Throwable又可分为ErrorException

  • Error:
    • AWTError
    • ThreadDeath
  • Exception:
    • RuntimeException
    • CheckedException

Error

Error指Java程序运行错误

  • 如果程序在启动时出现Error,则启动失败

  • 如果程序在运行过程中出现Error,则系统推出进程

  • 出现Error通常是因为系统的内部错误,或者资源耗尽,Error不能在运行过程中动态处理

  • 如果出现Error,则系统能做的工作只有几率错误原因和安全终止

Exception

  • Exception指Java程序运行异常,即运行中的程序发生了人们不期望的事件,可以被Java异常处理机制处理
  • Exception是程序开发中异常处理的核心,可分为RuntimeException运行时异常CheckException检查异常
  • RuntimeException

    指在JVM正常运行期间抛出的异常

    • RuntimeException可以被捕获处理,如果出现它,那么一定是程序发生错误导致的
    • 需要抛出异常或者捕获处理该异常
    • 常见的RuntimeException有:NullPointerExceptionClassCastExceptionArrayIndexOutOfBundsException
  • CheckedException

    只在编译器Java编译器会检查CheckedException异常并强制程序捕获并处理该异常,即要求程序在可能出现异常的地方通过try catch语句捕获并处理异常

    • 常见的ChechedException有IOExceptionSQLExceptionClassNotFoundException等。这类异常通常由于打开错误文件、SQL语法错误、类不存在等问题引起

处理异常

  • 抛出异常
  • 使用try catch捕获并处理异常

抛出异常

遇到异常时不进行具体处理,而是将异常抛给调用者,由根调用者根据情况处理

抛出异常有三种形式:

  1. throws
  2. throw
  3. 系统自动抛出异常
  • throws:作用在方法上,用于定义方法可能抛出的异常
  • throw:作用在方法内,表示明确抛出一个异常
public static void main(String[] args) {
String str = "hello world";
int index = 10;
if (index >= str.length()){
throw new StringIndexOutOfBoundsException();
}else{
str.substring(0, index);
}
}
int div(int a, int b) throws Exception {
return a / b;
}

try catch处理异常

使用try catch捕获并处理异常,能够针对性的处理每种可能的异常,并在捕获到异常后根据不同的情况做处理,try中写可能出现异常的代码,catch中指定要捕获的异常种类,并列出相应的处理代码,finally中写无论异常是否发生都一定要被执行的代码,常用来关闭连接资源等

try {
// 可能出现异常的代码
} catch (XxxException e) {
// 捕获到异常后的处理代码
} finally {
// 不论异常是否发生,都要执行的代码
// 常用来释放资源
}

throwthrows的区别

  • 位置不同
    • throws作用在方法上,后面跟着的是异常类
    • throw作用在方法内,后面跟着的是异常对象
  • 功能不同
    • throws用来声明方法在运行过程中可能出现的异常,以便调用者根据不同的异常类型预先定义不同的处理方式
    • throw用来抛出封装了异常信息的对象,程序在执行到throw时后续的代码不再执行,而是跳到调用者,并将异常信息抛给调用者
    • throw如果执行了,则它后面的语句无法执行,除了finally中的语句

自定义异常

Java提供的异常类不够我们使用需要自己定义一些异常类,格式:

public class xxxException extends Exception / RuntimeException{
添加无参构造方法
带异常信息的构造方法
}

注意:

  1. 自定义异常类一般都是以Exception结尾,说明该类是一个异常类
  2. 自定义异常类必须继承Exception/RuntimeException
    • 继承Exception编译期异常,必须throwstry..catch
    • 继承RuntimeException 运行时异常,无需处理,交给JVM处理(中断处理)
  • 自定义一个异常类
public class RegisterException extends Exception {
/***
* 无参构造方法
*/
public RegisterException() {
super();
}
/***
* 带异常信息的构造方法
* 所有的异常类都会有一个带异常信息的构造方法,内部调用父类带异常信息的构造方法,让父类来处理异常
*/
public RegisterException(String message) {
super(message);
}
}

练习:

  1. 用数组保存已经注册过的数据名(DB)
  2. 使用Scanner获取用户输入的注册的用户名(前端,页面)
  3. 定义一个方法,对用户输入的注册用户名进行判断
    • 遍历存储已经注册用户名的数组,发现一致就抛出异常
    1. 循环结束发现没找到重复用户名,提示,“恭喜您注册成功”
class Test1 {
static String[] userNames = {"张三", "李四", "王五"};
/***
* 1.用数组保存已经注册过的数据名(DB)
* 2.使用Scanner获取用户输入的注册的用户名(前端,页面)
* 3.定义一个方法,对用户输入的注册用户名进行判断
* - 遍历存储已经注册用户名的数组,发现一致就抛出异常
*
* 4.循环结束发现没找到重复用户名,提示,“恭喜您注册成功”
*/
public static void main(String[] args) throws RegisterException {
//使用Scanner
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要注册的用户名");
String userName = sc.next();
cheakUserName(userName);
}
/***
* 对用户名进行判单
*/
public static void cheakUserName(String userName) {
for (String name : userNames) {
if (name.equals(userName)) {
try {
throw new RegisterException("该用户名已被注册");
} catch (RegisterException e) {
e.printStackTrace();
return;
}
}
}
//循环结束没找到
System.out.println("恭喜您注册成功");
}
}