异常(重要)
概述:就是程序出现了错误的情况。
所有异常和错误的顶级父类 Throwable(抽象类) 定义了所有异常和错误的共性内容。
1. 异常的体系
- Error :系统级别的错误,开发者不处理(硬件层面的问题)
- Exception : 程序级别的错误,开发者要处理。(程序运行的问题)
- Expcetion和其所有子类(不包括RuntimeException) : 编译期异常。
- RuntimeException和其所有的子类 :运行期异常。
Java中有很多异常类,每一个异常类都用于描述一种错误的情况,如果真的出现了错误情况的时候,认为代码不能向下继续执行的时候,就需要抛出异常提醒调用者!
抛异常的方式:
throw new 异常类名();
2. 抛异常的时机
当经过代码的校验,认为程序已经不满足向下继续执行的情况的时候,抛出异常!
抛异常之后的默认处理:
3. 抛出运行期异常对象的处理方案
如果抛出的是运行期异常,那么直接抛出即可,不需要进行任何的额外处理!
public static int getElement(int[] arr, int index) { //判断索引是否合法 if (index < 0 || index >= arr.length) { //执行到if中认为代码已经不具备向下继续运行的条件了,抛出异常! (1)选一个用于描述本次异常的异常类ArrayIndexOutOfBoundsException (2)抛 throw new ArrayIndexOutOfBoundsException(); } return arr[index];}
4. 抛出编译期异常对象的处理方案
如果抛出的是编译期异常,那么除了抛出的语句之外,还要在当前方法上强制进行可能会抛出异常的声明!
public static void throwException() throws ParseException {
//模拟经过判断出现错误情况抛出异常
if (true) {
throw new ParseException("zhangergou", 10); //关心异常如何抛出,不要关心参数。
}
}
当方法抛出了编译期异常之后,要在方法形式参数()的后面基于throws 异常类名进行声明!
声明的目的就是告诉调用者该方法可能会出现异常,需要调用者进行处理!
5.如何处理运行期异常
不处理。
public static void main(String[] args){
getElement();
}
public static int getElement(int[] arr, int index) {
//判断索引是否合法
if (index < 0 || index >= arr.length) {
//执行到if中认为代码已经不具备向下继续运行的条件了,抛出异常! (1)选一个用于描述本次异常的异常类ArrayIndexOutOfBoundsException (2)抛
throw new ArrayIndexOutOfBoundsException();
}
return arr[index];
}
(1)作为调用者而言,在调用一个方法的时候,如果方法中抛出了运行期异常,调用者是没有感知。
不能因为可能会出现的运行期异常刻意的去做防范,耗费精力。
(2)如果没有处理,代码执行过程中真的出现了运行期异常,回去改代码。
6. 如何处理编译期异常
(1)编译期异常的处理方式-甩锅处理法
核心思想:作为调用者也不知道如何处理,那么就继续向上抛出。
public static void functionOne() throws ParseException {
//基于SimpleDateFormat调用parse方法解析字符串变为日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
Date resultDate = sdf.parse("2022年12月12日 12时12分12秒");
}
具体操作: 将光标放到红线方法上后,使用万能键Alt+Enter,选择第一个Add Exception to method signature。
学习阶段遇到的所有编译期异常,没有特殊要求的情况下,一律抛出!(甩锅)
(2)编译期异常的处理方式-背锅处理法
核心思想:基于Java提供的一种处理异常的语法格式进行处理。try…catch…
try {
//可能出现异常的代码
} catch (可能出现的异常类名 变量名) {
//捕获到对应异常的处理方法
} catch (可能出现的异常类名 变量名) {
//捕获到对应异常的处理方法
}
先抓小的,再抓大的! catch(Exception c){} 兜底!
try {
//(1)在try中调用可能会出现异常的代码;
functionOne();
} catch (ParseException e) { //(2)在catch中必须声明捕获可能出现的编译期异常
//(3)基于捕获到的异常对象可以调用从Throwable继承的一些成员方法
System.out.println(e.getMessage()); //提示信息
System.out.println(e.toString()); //将异常对象转化为字符串(异常类+提示信息)
e.printStackTrace(); //打印异常中保存的堆栈信息(代码到底在一行出的错)
}
7. 自定义异常
Java定义这些异常是用于描述核心类库中的一些代码执行错误的情况的!
这些异常并不能用于描述所有项目中产生问题的情况,需要开发者自己定义异常类,来用于描述自己项目中的问题!
自定义异常的步骤:
(1)明确要创建的异常是编译期异常还是运行期异常。
如果是编译期就继承Exception,如果是运行期就继承RuntimeException。
(2)生成构造方法,无参 + 传递String类型提示信息的有参构造。
//(1)根据当前自定义异常类的实际情况继承RuntimeException或者是Exception
public class RegisterException extends RuntimeException {
//(2)生成构造方法 无参:创建对象 有参:访问父类传递String提示信息参数的构造
public RegisterException() {
}
public RegisterException(String message) {
super(message);
}
}
自定义异常的使用方式:
public static void main(String[] args) {
//模拟用户注册 用户名:必须是6-8位的数字,字母,下划线组成。密码:6位密码纯数字。
Scanner sc = new Scanner(System.in);
System.out.println("请您输入用户名(6-8位由数字,字母,下划线组成):");
String username = sc.next();
System.out.println("请您输入密码(6位由数字组成):");
String password = sc.next();
if (!username.matches("\\w{6,8}"))
throw new RegisterException("您的用户名不满足6-8位由数字,字母,下划线组成的要求!");
if (!password.matches("\\d{6}"))
throw new RegisterException("您的密码不满足6位由数字组成的要求!");
System.out.println("您注册成功,用户名:" + username + " 密码:" + password + " 请您妥善保管!");
}