☰
异常基础知识
2026/10/11 1:37:14 网站建设 项目流程

一、什么是异常

1. 概念

异常,就是程序运行过程中出现的非正常情况。 当代码出现错误,JVM 会创建异常对象,封装错误信息,然后终止程序。

注意:语法错误不属于异常!语法错误在编译阶段就无法通过,根本不能运行;异常是代码编译成功,运行的时候才发生的错误。

2. 异常体系总览

Java 中所有异常 / 错误的顶层父类:java.lang.Throwable

  • Error:严重错误,无法处理,程序直接崩溃。比如内存溢出 OOM、栈溢出 StackOverflowError,程序员不能干预。
  • Exception:异常,是我们需要处理的,分为两大类:
    1. 编译时异常(受检异常 CheckedException)
    2. 运行时异常(非受检异常 RuntimeException)

二、运行时异常与编译时异常

1. 运行时异常 RuntimeException

  • 发生时机:程序运行的时候才抛出
  • 编译器不强制要求处理,不写 try-catch 或者 throws 也能编译通过
  • 大多是代码逻辑问题,写代码时规避即可
  • 常见例子:
    • NullPointerException空指针异常
    • ArrayIndexOutOfBoundsException数组下标越界
    • ArithmeticException算术异常(除 0)
    • ClassCastException类型转换异常
public class Demo { public static void main(String[] args) { int a = 10; int b = 0; //运行时异常:ArithmeticException,编译不会报错,运行才崩溃 System.out.println(a / b); } }

2. 编译时异常(受检异常)

  • 发生时机:编译阶段编译器就会检查
  • 编译器强制要求处理,不处理代码直接编译报错,无法运行
  • 大多是外部环境问题,不是代码逻辑 bug,例如文件找不到、IO 读取失败
  • 常见例子:IOException、FileNotFoundException
import java.io.FileReader; public class Demo { public static void main(String[] args) { //FileNotFoundException属于编译时异常,编译器强制要求处理 FileReader fr = new FileReader("test.txt"); } }

上面这段代码直接报红,编译失败,必须用try-catch捕获或者throws抛出异常。

对比表格

类型父类编译是否强制处理产生原因
运行时异常RuntimeException❌ 不强制代码逻辑错误,比如空指针、下标越界
编译时异常Exception(非 Runtime)✅ 强制处理外部资源问题:文件、网络、IO 等

三、异常的产生及处理

1. 异常产生的底层流程

  1. 代码执行出错,JVM 自动创建对应异常对象,包含异常类型、错误信息、栈追踪信息
  2. JVM 把异常抛出,传递给调用者
  3. 如果调用者没有处理,异常继续向上传递,直到 main 方法
  4. main 方法也不处理:JVM 打印异常栈信息,终止整个程序

默认情况:异常一旦抛出,后面代码不再执行。

2. 异常处理两大方案

方案① try-catch-finally 捕获异常(自己处理)

语法格式:

try{ // 可能出现异常的代码 }catch(异常类型 e){ // 捕获到对应异常后,执行的处理逻辑 }finally{ // 无论是否发生异常,**一定会执行**的代码(资源释放) }

代码示例:

public class ExceptionDemo { public static void main(String[] args) { int a = 10; int b = 0; try{ //可能抛出异常的代码 System.out.println(a / b); System.out.println("try中异常后面的代码,异常发生不会执行"); }catch (ArithmeticException e){ //捕获算术异常,在这里处理 System.out.println("捕获到除零异常!"); //打印异常详细信息,调试使用 e.printStackTrace(); }finally { System.out.println("finally代码块,无论有没有异常都会执行"); } //捕获异常后,程序不会崩溃,可以继续往下执行 System.out.println("main方法继续运行"); } }

finally 典型用途:关闭 IO 流、数据库连接等资源。 注意:唯一让 finally 不执行的情况:代码执行System.exit(0);退出 JVM。

方案② throws 声明抛出异常(交给调用者处理)

写在方法签名后,告诉调用者:这个方法有可能抛出异常,调用者需要处理。

注意:throws 只是声明异常,不会处理异常,异常继续向上传递。

import java.io.FileReader; import java.io.IOException; public class Demo { //throws声明,抛出编译时异常IOException,交给调用main方法处理 public static void readFile() throws IOException { FileReader fr = new FileReader("test.txt"); } public static void main(String[] args) throws IOException { readFile(); } }

3. 多异常捕获写法

try{ //可能产生多种异常 }catch(NullPointerException e){ System.out.println("空指针"); }catch(ArrayIndexOutOfBoundsException e){ System.out.println("数组越界"); } //JDK7新特性:同类型处理可以合并捕获 catch(ArithmeticException | ClassCastException e){ System.out.println("算术或者类型转换异常"); }

捕获多个异常时,父类异常要写在子类异常后面,否则编译报错。

四、throw 手动抛出异常

主动创建异常对象,手动抛出。

throws:写在方法上,声明异常;throw:方法内部,抛出异常对象。

public class Demo { public static void checkAge(int age){ if(age < 0 || age >120){ //手动创建异常对象抛出 throw new RuntimeException("年龄非法!"); } System.out.println("年龄合法"); } public static void main(String[] args) { checkAge(-10); } }

五、高频易错点

  1. 运行时异常编译器不强制捕获,但是一旦发生,程序依然会终止;
  2. try 中代码出现异常,try 内异常之后的代码不再执行;
  3. finally 一定会执行,除非 JVM 退出(System.exit);
  4. throws 仅仅是声明,没有处理异常;throw 才是抛出异常;
  5. 捕获多异常,父类异常不能写在前面,会把子类异常全部拦截。

六、核心总结

  1. Throwable 分为 Error(无法处理)和 Exception(需要处理)
  2. Exception 分编译时异常(强制处理)、运行时异常(不强制)
  3. 处理异常两种方式:try-catch 捕获,throws 抛出给上层调用者
  4. finally 用于资源释放,必定执行
  5. throw 手动抛出异常对象

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询