本专题主要为观看韩顺平老师《零基础30天学会Java》课程笔记,同时也会阅读其他书籍、学习其他视频课程进行学习笔记总结。如有雷同,不是巧合!
三、异常处理机制
异常处理机制是一种结构化的错误处理方式,用于管理程序运行时可能出现的异常情况(如文件不存在、网络中断、空指针访问等)。它允许程序在遇到错误时进行合理的处理,而不是直接崩溃。剩下的程序会继续执行。
-Java 提供了三种主要的异常处理机制:
1. try-catch-finally块
程序员在代码中捕获发生的异常,并自行处理。
try {
// 可能抛出异常的代码
} catch (ExceptionType1 e1) {
// 将异常发生时,系统将异常封装成Exception对象e,并传递给catch
// 处理 ExceptionType1 类型的异常
} catch (ExceptionType2 e2) {
// 处理 ExceptionType2 类型的异常
} finally {
// 无论是否发生异常都会执行的代码
// 常用于资源清理
// 如果没有finally,语法也可以通过
}



-
可以直接用
try-finally,相当于没有捕获异常,程序会直接崩掉(finally后),但在finally中的块还是会执行。 finally块中的return语句会覆盖try或catch块中的return语句:finally块的设计初衷是无论发生什么(正常执行、异常抛出、try/catch中有return),finally块中的代码都必须被执行。这个“必须执行”的原则优先级非常高。
-
例题:


题目1:
当 catch 块中遇到 return 3; 时,JVM 并不会立即结束方法调用。它的执行流程如下:
catch块开始执行:JVM 准备返回3- 暂停返回操作:在真正返回之前,JVM 必须先去执行
finally块,因为这是语言规范强制要求的 - 执行
finally块:进入finally块后,执行return 4; finally中的return生效:finally块中的return 4;现在成为新的返回指令- 忽略之前的返回值:
catch块中准备的return 3;被完全忽略和覆盖
题目2:
catch (NullPointerException e)捕获异常,执行return ++i;:i先自增为3,然后return 3;(此时3被存入临时变量,但还未真正返回)
finally块执行:++i;→i变为4。System.out.println("i=" + i);→ 打印i=4finally块没有return,所以不会覆盖catch的返回值
- 最终返回值:
catch块返回的是3(临时变量存储的值),因此main方法打印
-
例题:如果用户输入的不是一个整数,就提醒他反复输入,直到输入一个整数为止。
方法一:使用
Scanner和try-catchimport java.util.Scanner; import java.util.InputMismatchException; public class IntegerInputValidation { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int number = 0; boolean validInput = false; while (!validInput) { try { System.out.print("请输入一个整数: "); number = scanner.nextInt(); validInput = true; // 只有成功读取整数才会执行到这里 } catch (InputMismatchException e) { System.out.println("错误:请输入有效的整数!"); scanner.nextLine(); // ⭐清除输入缓冲区中的错误内容 } } System.out.println("您输入的整数是: " + number); scanner.close(); } }通过捕获
InputMismatchException(Scanner特有的异常),直到获得合法整数。import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String input; int num; while (true) { try { System.out.print("输入一个整数:"); input = scanner.nextLine(); num = Integer.parseInt(input); break; } catch (NumberFormatException e) { e.printStackTrace(); } } System.out.println("输入的整数是:" + num); } }方法二:使用
BufferedReader和NumberFormatExceptionimport java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class IntegerInputValidation2 { public static void main(String[] args) { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); int number = 0; boolean validInput = false; while (!validInput) { try { System.out.print("请输入一个整数: "); String input = reader.readLine(); number = Integer.parseInt(input); validInput = true; } catch (NumberFormatException e) { System.out.println("错误:请输入有效的整数!"); } catch (IOException e) { System.out.println("输入输出错误!"); } } System.out.println("您输入的整数是: " + number); } }捕获
NumberFormatException(字符串转数字时的异常),每次读取新的一行,不需要额外处理。
2. throws 关键字
将发生的异常抛出,交给调用者(方法)处理,最顶级的处理者是JVM【打印异常信息,并直接退出程序】。


public void readFile(String filePath) throws IOException, FileNotFoundException {
// 可能抛出 IOException 的代码
}
如果出现运行时异常,没有使用try-catch处理,会有默认的throws Exception动作,如果调用它的方法没有处理,则默认丢给JVM。
-
子类重写父类的方法时,所抛出的异常要么和父类抛出的异常一致,要么是父类抛出的异常类型的子类型。
-
如果一个方法具有编译异常,则必须显式抛出或者用
try-catch处理异常;调用它的方法(直到main)也是同样的要求(最终必须有一个方法处理异常(否则编译失败)) ,否则代码将无法通过编译。import java.io.FileInputStream; import java.io.FileNotFoundException; public class Solution { public static void main(String[] args) { f1(); } public static void f1() { f3(); } public static void f3() { FileInputStream fis = new FileInputStream("1111.txt"); } }
- 不是每个方法都必须
try-catch,可以选择:- 当前方法处理(
try-catch) - 继续向上抛出(
throws)
- 当前方法处理(
public static void main(String[] args) {
try {
methodA(); // 最终在 main 处理异常
} catch (IOException e) {
System.out.println("main 处理异常: " + e.getMessage());
}
}
static void methodA() throws IOException {
methodB(); // 不处理,继续向上抛出
}
static void methodB() throws IOException {
throw new IOException("IO错误!");
}
3. throw 关键字
使用 throw 关键字可以显式抛出异常:
if (someCondition) {
throw new IllegalArgumentException("Invalid argument");
}
四、自定义异常
当程序中出现了某些“错误”,但该错误信息并没有在Throwable子类中描述处理,可以创建自己的异常类来代表特定的错误情况。
自定义异常的步骤
- 定义异常类名,并继承
Exception或RuntimeException - 如果继承
Exception,输入编译异常 - 否则属于运行异常【通常情况】,可以使用默认的处理机制,否则下图的main方法要显式地
throws AgeException

五、throw&throws

1. throw 关键字
作用:主动抛出一个异常对象(可以是 checked exception 或 unchecked exception)。
特点:
- 用于方法内部
- 后面跟一个异常对象实例
- 执行到
throw语句时,当前方法会立即终止
语法:
throw new ExceptionType("异常信息");
示例:
void validateAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
if (age > 120) {
throw new RuntimeException("年龄不合法");
}
}
2. throws 关键字
作用:在方法签名中声明该方法可能抛出的异常类型。
可以声明运行时异常(RuntimeException 及其子类),但这样做通常没有实际意义,因为运行时异常是 unchecked exceptions(非受检异常),调用方并不强制要求处理它们。
特点:
- 用于方法声明处
- 后面跟一个或多个异常类名
- 不实际抛出异常,只是声明可能性
- 调用该方法的地方必须处理这些异常
语法:
returnType methodName(parameters) throws ExceptionType1, ExceptionType2 {...}
示例:
void readFile(String path) throws FileNotFoundException, IOException {
// 方法实现可能抛出这些异常
}
对比
| 特性 | throw | throws |
|---|---|---|
| 位置 | 方法内部 | 方法声明处 |
| 作用 | 主动抛出异常 | 声明可能抛出的异常 |
| 后跟内容 | 异常对象实例(new Exception()) | 异常类名(Exception.class) |
| 数量 | 一次只能抛出一个异常 | 可以声明多个异常(逗号分隔) |
| 异常类型 | 可以是 checked 或 unchecked | 只能是 checked exceptions |
组合使用示例
throw抛出编译异常,必须捕获或throws抛出让调用方法处理;抛出运行时异常,不需要强制处理。
// 声明可能抛出IOException(throws)
public void processFile(String filename) throws IOException {
if (filename == null) {
// 主动抛出异常(throw)
throw new IllegalArgumentException("文件名不能为null");
}
BufferedReader reader = new BufferedReader(new FileReader(filename));
// 这里可能抛出FileNotFoundException(是IOException的子类)
String line = reader.readLine();
reader.close();
}
-
例题:
finally块执行完后,才会回来执行try或catch中的return或throw语句,若finally中有return或throw等终止访问的语句,则不会跳回执行,直接停止

4102

被折叠的 条评论
为什么被折叠?



