目录
一、先搞懂:异常到底是什么?(大白话解释)
二、Java 异常的两大分类(核心!记清这两类就够了)
1. 运行时异常(非检查型异常)—— 最常见,可处理可不处理
核心特点
常见例子(记这 5 个,覆盖 80% 开发场景)
2. 编译时异常(检查型异常)—— 编译器强制要求处理,不处理编译报错
核心特点
常见例子(记这 3 个,覆盖开发常用场景)
两类异常核心对比(一张表记牢)
三、异常处理的 3 个核心关键字 ——try、catch、finally(零基础必学)
核心思想
基础语法模板(死记硬背,直接套用)
关键规则(零基础必看,避免踩坑)
入门示例 1:处理运行时异常(除以 0,ArithmeticException)
入门示例 2:多 catch 块(处理多种不同异常)
入门示例 3:finally 的核心作用 —— 释放资源(必用场景)
四、处理编译时异常的 2 种方式(编译器强制要求,二选一)
方式 1:try-catch-finally 捕获处理(推荐,主动处理异常)
示例:处理控制台输入的 IOException(编译时异常)
方式 2:throws 声明异常(甩锅,把异常交给上层处理)
示例:main 方法 throws 声明 IOException,甩锅给 JVM
两种方式对比(零基础怎么选?)
五、2 个进阶关键字:throw(主动抛异常)、throws(声明异常)
1. throw —— 手动 / 主动抛出一个异常(方法内部用)
作用
语法
示例:主动抛出非法参数异常(IllegalArgumentException,运行时异常)
2. throws —— 声明方法可能抛出的异常(方法名后面用)
作用
示例:方法内 throw 异常,方法名后 throws 声明
throw 和 throws 核心区别(一张表分清,不混淆)
六、零基础异常处理的 5 个黄金原则(避坑必备,直接套用)
原则 1:局部变量必须初始化,避免 “未初始化” 导致的异常
原则 2:调用对象的方法 / 属性前,先判空(避免空指针)
原则 3:资源使用后必须关闭,且关闭前要判空
原则 4:catch 块要针对性处理,不要只写一个 Exception
原则 5:运行时异常尽量处理,编译时异常必须处理
七、零基础快速上手总结(核心知识点浓缩,一分钟回顾)
本文专为 Java 零基础小白打造,用通俗的语言、直白的例子讲清异常是什么、异常有哪些、怎么处理异常、如何主动抛异常,全程避开复杂术语,学完就能上手写异常处理代码,轻松搞定 Java 异常核心知识点!
一、先搞懂:异常到底是什么?(大白话解释)
你写的 Java 代码,编译没报错,但运行时突然崩了 / 出问题,这种运行时的错误 / 意外情况,就是 Java 中的异常。
- 比如:用一个数除以 0(int a = 10 / 0;)、访问数组时下标越界(int[] arr = {1,2}; arr[5] = 3;)、读取文件时文件不存在,这些都会触发异常。
- 没有异常处理时,程序会直接终止运行,并在控制台打印一堆红色的错误信息,体验极差;有了异常处理,我们可以捕获错误、优雅处理,让程序继续运行,还能给用户友好提示。
简单类比:你出门逛街(程序运行),突然下雨了(异常)—— 没准备的话会被淋成落汤鸡(程序终止);带了伞(异常处理),就能正常继续逛街(程序运行)。
二、Java 异常的两大分类(核心!记清这两类就够了)
Java 把所有异常分成两大阵营,处理规则完全不同,零基础先记清这两类的区别,不用记复杂的继承关系,记住「特点 + 例子 + 处理方式」即可。
1. 运行时异常(非检查型异常)—— 最常见,可处理可不处理
核心特点
- 编译时不强制要求处理,编译器不会报错,写代码时不用管也能编译通过;
- 错误通常是程序员写代码的疏忽导致(比如粗心写了除以 0、下标越界);
- 运行时才会触发,触发后若未处理,程序直接终止。
常见例子(记这 5 个,覆盖 80% 开发场景)
| ArithmeticException | 整数除以 0(10/0) | 数学运算错误 |
| ArrayIndexOutOfBoundsException | 数组下标超出范围(arr[5],数组只有 3 个元素) | 数组下标越界 |
| NullPointerException | 调用 null 对象的方法 / 属性(String s = null; s.length();) | 空指针(对象没创建就用) |
| InputMismatchException | Scanner 读取数据类型不匹配(用nextInt()读了字母) | 输入的类型不对 |
| ClassCastException | 错误的类型转换(Object o = "abc"; int a = (int)o;) | 类型强转失败 |
2. 编译时异常(检查型异常)—— 编译器强制要求处理,不处理编译报错
核心特点
- 编译时必须手动处理,否则代码连编译都通不过(编译器直接标红);
- 错误通常是程序外部的客观原因导致,不是程序员粗心(比如要读的文件被删了、网络断了);
- 属于 “可预见的意外”,Java 强制要求程序员提前做处理(比如文件不存在要提示,不能让程序直接崩)。
常见例子(记这 3 个,覆盖开发常用场景)
| IOException | 文件读取 / 写入、控制台输入输出异常 | IO 操作(文件 / 流)错误 |
| FileNotFoundException | 读取文件时,文件不存在 | 文件没找到 |
| SQLException | 连接数据库、操作数据库表失败 | 数据库操作错误 |
两类异常核心对比(一张表记牢)
| 编译要求 | 不强制处理,编译不报错 | 必须处理,不处理编译报错 |
| 触发原因 | 程序员代码疏忽(主观) | 程序外部客观原因(客观) |
| 处理优先级 | 建议处理,避免程序运行崩 | 必须处理,否则代码无法运行 |
| 常见触发阶段 | 运行时 | 编译时检查,运行时触发 |
三、异常处理的 3 个核心关键字 ——try、catch、finally(零基础必学)
这是 Java 处理异常的基础核心语法,也是最常用的方式,作用是「捕获异常→处理异常→保证收尾操作执行」,三者配合使用,语法固定,背会模板直接套就行。
核心思想
把可能触发异常的代码放进try块,把异常发生后的处理逻辑放进catch块,把无论是否发生异常都必须执行的收尾代码放进finally块(比如关闭文件、关闭 Scanner)。
基础语法模板
try {
// 第一步:放【可能触发异常】的代码
// 比如:除以0、Scanner读取、文件读取等
可能出问题的代码;
} catch (异常类型 异常变量名) {
// 第二步:捕获指定类型的异常,发生时执行这里的代码
// 比如:打印错误信息、给用户提示、重新赋值等
异常处理逻辑; // 如System.out.println("出错了!");
} finally {
// 第三步:无论是否发生异常,这里的代码【一定执行】
// 作用:收尾操作(关闭资源、释放内存)
必须执行的收尾代码; // 如sc.close();、关闭文件流等
}
关键规则(零基础必看,避免踩坑)
入门示例 1:处理运行时异常(除以 0,ArithmeticException)
最基础的try-catch-finally用法,处理新手最容易犯的 “除以 0” 错误:
public class ExceptionTest1 {
public static void main(String[] args) {
int a = 10;
int b = 0;
int result = 0; // 初始化结果,避免未赋值报错
try {
// 可能出问题的代码:除以0,会触发ArithmeticException
result = a / b;
System.out.println("两数相除结果:" + result); // 异常后,这行代码不会执行
} catch (ArithmeticException e) {
// 捕获算术异常,处理逻辑:提示错误
System.out.println("出错啦!原因:不能除以0");
// 可选:打印详细错误信息(开发调试用,上线后可注释)
// e.printStackTrace();
} finally {
// 无论是否出错,一定执行:收尾提示
System.out.println("异常处理代码执行完毕");
}
// 有异常处理,程序不会终止,这里能正常执行
System.out.println("程序继续运行,不受异常影响");
}
}
运行结果:
出错啦!原因:不能除以0
异常处理代码执行完毕
程序继续运行,不受异常影响
✅ 效果:原本会让程序终止的 “除以 0” 错误,被捕获处理后,程序能继续运行!
入门示例 2:多 catch 块(处理多种不同异常)
当try里的代码可能触发多种异常时,写多个catch块,针对性处理(比如同时可能除以 0、空指针):
public class ExceptionTest2 {
public static void main(String[] args) {
int a = 10;
int b = 0;
String s = null; // 空字符串,调用length()会触发空指针
try {
int result = a / b; // 可能触发ArithmeticException
s.length(); // 可能触发NullPointerException(若上面代码没触发异常)
} catch (ArithmeticException e) {
// 专门处理除以0异常
System.out.println("处理算术异常:不能除以0");
} catch (NullPointerException e) {
// 专门处理空指针异常
System.out.println("处理空指针异常:对象不能为null");
} catch (Exception e) {
// 万能异常捕获:所有异常的父类,捕获上面没写到的其他异常
System.out.println("处理其他未知异常:" + e.getMessage());
} finally {
System.out.println("多catch块的收尾操作");
}
}
}
运行结果:
处理算术异常:不能除以0
多catch块的收尾操作
✅ 关键:Exception是所有 Java 异常的父类,写在最后一个catch块,能捕获所有未明确声明的异常,避免漏捕。
入门示例 3:finally 的核心作用 —— 释放资源(必用场景)
开发中finally最常用的场景是关闭资源(比如 Scanner、文件流、数据库连接),无论是否发生异常,资源必须关闭,否则会占用系统内存,这是编程好习惯!
import java.util.Scanner;
import java.util.InputMismatchException;
public class ExceptionTest3 {
public static void main(String[] args) {
Scanner sc = null; // 先声明为null,方便finally中关闭
try {
sc = new Scanner(System.in);
System.out.print("请输入一个整数:");
int num = sc.nextInt(); // 输入字母会触发InputMismatchException
System.out.println("你输入的整数是:" + num);
} catch (InputMismatchException e) {
System.out.println("出错啦!你输入的不是整数");
} finally {
// 无论是否输入正确,都关闭Scanner,释放输入流资源
if (sc != null) { // 判空:避免sc为null时调用close()触发空指针
sc.close();
System.out.println("Scanner已关闭,资源释放");
}
}
}
}
运行场景 1:输入正确(整数 10)
请输入一个整数:10
你输入的整数是:10
Scanner已关闭,资源释放
运行场景 2:输入错误(字母 a)
请输入一个整数:a
出错啦!你输入的不是整数
Scanner已关闭,资源释放
✅ 效果:无论输入是否正确(是否触发异常),finally里的关闭资源代码一定会执行!
四、处理编译时异常的 2 种方式(编译器强制要求,二选一)
编译时异常(如 IOException)的特点是不处理编译就报错,Java 提供了2 种合法处理方式,零基础记住 “二选一” 即可,不用纠结,根据场景选择。
方式 1:try-catch-finally 捕获处理(推荐,主动处理异常)
和处理运行时异常的语法完全一样,把可能触发编译时异常的代码放进try块,catch块处理即可,编译器就不会报错了。
示例:处理控制台输入的 IOException(编译时异常)
// 必须导入io包,否则编译报错
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException; // 编译时异常
public class CheckedExceptionTest1 {
public static void main(String[] args) {
BufferedReader br = null;
try {
// 这行代码会触发IOException(编译时异常),必须处理
br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入一句话:");
String line = br.readLine();
System.out.println("你输入的是:" + line);
} catch (IOException e) {
// 捕获并处理IOException
System.out.println("输入异常:" + e.getMessage());
} finally {
// 关闭资源,避免内存泄漏
if (br != null) {
try {
br.close(); // close()也会触发IOException,嵌套try-catch即可
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
✅ 效果:用try-catch捕获后,编译器不再报错,程序正常编译运行。
方式 2:throws 声明异常(甩锅,把异常交给上层处理)
在方法名后面加throws 异常类型,表示 “这个方法里可能触发该异常,我不处理,交给调用这个方法的上层代码处理”。
- 若主方法(main)用throws声明,就表示把异常交给JVM(Java 虚拟机) 处理,JVM 的处理方式是:打印错误信息,终止程序(和未处理运行时异常的效果一样);
- 适合快速开发、测试场景,生产环境不推荐主方法用 throws(会导致程序终止)。
示例:main 方法 throws 声明 IOException,甩锅给 JVM
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
// main方法后加throws IOException,声明该方法可能抛出此异常,交给JVM处理
public class CheckedExceptionTest2 {
public static void main(String[] args) throws IOException {
// 触发IOException的代码,无需try-catch,编译器不报错
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入一句话:");
String line = br.readLine();
System.out.println("你输入的是:" + line);
br.close();
}
}
✅ 效果:编译器不报错,程序能正常运行;若触发异常,JVM 会打印红色错误信息,程序终止。
两种方式对比(零基础怎么选?)
| 核心思想 | 主动处理,解决异常 | 被动甩锅,交给上层处理 |
| 程序影响 | 异常处理后,程序可继续运行 | 上层若未处理,触发后程序直接终止 |
| 适用场景 | 生产环境、需要程序优雅运行的场景 | 测试场景、快速开发,无需处理异常 |
| 推荐程度 | 高(开发首选) | 低(仅临时使用) |
五、2 个进阶关键字:throw(主动抛异常)、throws(声明异常)
零基础掌握上面的try-catch-finally就够日常开发了,这里简单讲throw和throws的区别(很多小白容易混淆),了解即可,后续进阶再深入使用。
1. throw —— 手动 / 主动抛出一个异常(方法内部用)
作用
在代码中主动触发一个异常(比如判断用户输入的年龄是负数,主动抛异常提示),让程序进入异常处理流程。
语法
throw new 异常类型("异常提示信息");
示例:主动抛出非法参数异常(IllegalArgumentException,运行时异常)
public class ThrowTest {
public static void main(String[] args) {
int age = -10; // 非法年龄:负数
try {
// 判断年龄非法,主动抛异常
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数!你输入的是:" + age);
}
System.out.println("你的年龄是:" + age);
} catch (IllegalArgumentException e) {
// 捕获主动抛出的异常,处理提示
System.out.println("捕获异常:" + e.getMessage());
}
}
}
运行结果:
捕获异常:年龄不能为负数!你输入的是:-10
✅ 效果:通过throw主动触发异常,替代了 “程序自动触发异常”,实现了自定义异常触发条件。
2. throws —— 声明方法可能抛出的异常(方法名后面用)
作用
告诉调用者 “这个方法内部可能会抛出这些异常,我没处理,你自己看着办”,就是之前讲的 “甩锅”,和throw是完全不同的东西(一个是声明,一个是执行)。
示例:方法内 throw 异常,方法名后 throws 声明
public class ThrowsTest {
// 方法名后throws声明:该方法可能抛出IllegalArgumentException
public static void checkAge(int age) throws IllegalArgumentException {
if (age < 0) {
// 方法内部throw,主动抛异常
throw new IllegalArgumentException("年龄不能为负数");
}
System.out.println("年龄合法:" + age);
}
public static void main(String[] args) {
try {
// 调用有throws声明的方法,要么try-catch处理,要么main方法也throws
checkAge(-5);
} catch (IllegalArgumentException e) {
System.out.println("处理异常:" + e.getMessage());
}
}
}
运行结果:
处理异常:年龄不能为负数
throw 和 throws 核心区别(一张表分清,不混淆)
| throw | 方法内部 | 主动 / 手动抛出一个异常 | throw new 异常类型(信息); |
| throws | 方法名后面 | 声明方法可能抛出多个异常 | 方法名() throws 异常1,异常2{} |
六、零基础异常处理的 5 个黄金原则(避坑必备,直接套用)
学完语法,更重要的是养成良好的异常处理习惯,这 5 个原则都是开发中总结的实战经验,零基础严格遵守,能避开 90% 的异常坑!
原则 1:局部变量必须初始化,避免 “未初始化” 导致的异常
方法内的局部变量(如int a;)没有默认值,若未赋值就使用,要么编译报错,要么运行时触发异常,声明时直接赋初始值(如int a = 0; String s = "";)。
原则 2:调用对象的方法 / 属性前,先判空(避免空指针)
空指针(NullPointerException)是开发中最常见的异常,只要调用对象的方法 / 属性(如s.length()),先加if (对象 != null)判空,再使用。
原则 3:资源使用后必须关闭,且关闭前要判空
使用 Scanner、文件流、数据库连接等资源后,一定要在finally块中关闭,关闭前必须判空(if (sc != null)),避免关闭 null 对象触发空指针。
原则 4:catch 块要针对性处理,不要只写一个 Exception
虽然Exception能捕获所有异常,但开发中要尽量写具体的异常类型(如ArithmeticException、InputMismatchException),针对性处理(比如除以 0 提示 “不能除 0”,输入错误提示 “类型不对”),方便调试和用户理解。
原则 5:运行时异常尽量处理,编译时异常必须处理
- 运行时异常(如下标越界)是程序员粗心导致,尽量用try-catch处理,避免程序运行时突然终止;
- 编译时异常(如 IOException)是 Java 强制要求,要么try-catch捕获,要么throws声明,二选一,不处理编译不过。
七、零基础快速上手总结(核心知识点浓缩,一分钟回顾)
至此,Java 异常的核心知识点已经全部讲完,零基础小白按照本文的模板套代码,就能轻松实现异常处理,让你的 Java 程序更健壮、更优雅!文章如有错误欢迎私信我,我会及时解决,如果我的内容对你有帮助和启发,请点赞、评论、收藏。你们的支持就是我更新最大的动力,那么我们下期再见!
网硕互联帮助中心





评论前必须登录!
注册