Java基础学习(七)
Java基础学习(七):异常机制
本文为个人学习记录,内容学习自 狂神说Java 和 黑马程序员
概念
异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等
异常发生在程序运行期间,它影响了正常的程序执行流程
简单分类
异常 vs 错误
-
异常(Exception)
-
异常是开发者可以在程序中进行处理的(可以通过编写异常处理语句,在出现异常时进行处理以恢复程序的正常运行)
-
检查性异常:在编译时由编译器强制检查的异常,开发者必须处理这些异常才能编译通过
-
运行时异常:在编译时可以被忽略的异常,程序运行时才会出现
-
-
错误(Error)
- 错误是开发者无法在程序中进行处理的(错误发生时就无力回天了,只能避免错误的发生)
- 当出现错误时,JVM 一般会直接终止线程
异常体系结构
-
Java 把异常当作对象来处理,并定义了一个基类
Java.lang.Throwable
作为所有异常的超类(即最顶层的类) -
在 Java API 中已经定义了许多异常类,这些异常类分成两大类 —— 错误和异常
-
下图给出了一些常见错误Error和异常Exception,仅表示大体结构,例如 RuntimeException 和 ArrayIndexOutOfBoundsException 中间还省略了一些子/父类
-
RuntimeException 本身和其所有子类构成了运行时异常,其余所有异常均为编译时异常
异常处理机制
-
抛出异常
int a = 1; int b = 0; System.out.println(a/b); // 由于0不能作为除数,程序会抛出异常 ========================================================================================================= 输出结果: Exception in thread "main" java.lang.ArithmeticException: / by zero
-
捕获异常
可以通过
try-catch
语句捕获异常,从而使程序在有异常的情况下继续执行int a = 1; int b = 0; try { System.out.println(a/b); // 将可能抛出异常的语句放入try修饰的代码块中 }catch (ArithmeticException e){ // 指明想捕获的异常类型 System.out.println("程序出现异常才会执行"); // 如果捕获到了指定异常会执行的语句,通常是处理语句 }finally { // finally代码块是可选项,无论是否捕获到异常都会执行 System.out.println("无论如何都会执行"); } System.out.println("继续执行"); // 就算存在异常,程序也会继续执行下去
几点补充:
-
想捕获的异常类型也可以是具体异常类的父类,例如写
catch (Throwable e)
时能够捕获到其下所有的错误和异常 -
catch 语句可以存在多个,类似于 else if 语句,从上往下执行当捕获到异常后就不会执行剩余的 catch 语句了
-
如果在 try 语句块内没有捕获到异常,那么 try 语句块中内容能正常执行,而 catch 语句块中的内容不会被执行
-
如果在 try 语句块内捕获到了指定异常,那么 try 语句块中异常之前的内容能正常执行,异常之后的内容不会再被执行
-
finally 语句块内的内容一定会执行,不管是不存在异常/存在异常且成功捕获/存在异常但未成功捕获,都会执行;如果 try 语句块中有 return,那么 finally 语句块会在 try 的 return 之前执行,所以此时若 finally 语句块中也有 return,那么后者会覆盖前者。但需要注意,try 中 return 的返回值在执行 finally 语句块前就确定了,只是先跳转到 finally 中执行完后再返回而已
-
JDK7 新增功能:如果存在多个 catch 语句块,且这些语句块的执行内容相同,那么可以在 catch 中同时捕获多个异常,例如:
catch (ArrayIndexOutOfBoundsException | ArithmeticException e) {}
-
-
主动抛出异常
注意:主动抛出异常后,剩余代码将不会继续执行,除非使用 try-catch 语句捕获异常(和程序自动抛出的异常同理)
-
方法内抛出异常(使用
throw
关键字)throw new ArithmeticException(); // 主动抛出一个算术异常
-
方法上抛出异常(使用
throws
关键字)- 写在方法定义处,用于告诉调用者本方法可能会有哪些异常,多个异常之间用逗号隔开
- 如果是编译时异常则必须要写,运行时异常可以省略不写
public static void main(String[] args) { int a = 1; int b = 0; try { test(a, b); } catch (ArithmeticException e) { System.out.println(""); } } public static void test(int a, int b) throws ArithmeticException{ // 使用throws关键字指定异常类型 System.out.println(a/b); }
-
异常中的常见方法
Throwable 的成员方法:
方法名 | 说明 |
---|---|
public String getMessage() | 返回此异常的消息 |
public String toString() | 返回此异常的描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
示例:
int[] arr = {1, 2, 3};
try {
System.out.println(arr[10]);
} catch (ArrayIndexOutOfBoundsException e) {
String str1 = e.getMessage();
String str2 = e.toString();
e.printStackTrace();
}
自定义异常
-
使用 Java 内置的异常类可以描述编程时出现的大部分异常情况
-
自定义异常的作用:让控制台的报错信息更加直观
-
自定义异常类的步骤:
-
定义异常类:起名需要见名知意
-
写继承关系:如果是编译时异常则继承 Exception 类,如果是运行时异常则继承 RuntimeException 类
-
构造函数:直接使用
alt+Insert
生成空参构造和形参为字符串的带参构造 -
示例:一个起名格式的自定义异常
public class NameFormatException extends RuntimeException { // 空参构造 public NameFormatException() { } // 带参构造 // 抛出异常时,可以通过throw new NameFormatException("名字格式有误")创建异常对象 // 这样在调用e.printStackTrace()时就可以输出自定义的异常信息 public NameFormatException(String message) { super(message); } }
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix