在 Java 的异常处理中,throw 关键字用于手动抛出一个异常对象,而 throws 关键字用于声明方法可能抛出的异常。下面详细介绍 Java 的最新异常处理机制及 try-catch-throw 的用法。


1. throw 关键字

throw 用于在代码中手动抛出一个异常,通常用于异常检测、错误处理或自定义异常。

throw 的作用

throw 关键字的主要作用是手动抛出异常,让程序在遇到错误时主动终止当前代码逻辑,并将异常交给上层代码处理。

在 Java 中,默认情况下,只有系统遇到错误时才会自动抛出异常,比如 NullPointerExceptionArithmeticException 等。但有时候,我们需要自己定义错误情况,并主动抛出异常,让调用者知道发生了问题,这时候就用 throw

语法:

1
throw new 异常类对象;`

示例:

1
2
3
4
5
6
7
8
9
10
11
public class ThrowExample {  
public static void checkAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("未成年人不能注册!");
}
System.out.println("注册成功!");
}
public static void main(String[] args) {
checkAge(15); // 这里会抛出异常
}
}

throw 的使用场景

1. 校验输入参数

比如,我们要实现一个方法,它只能处理年龄 >= 18 的情况,如果年龄小于 18,就应该报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ThrowExample {
public static void checkAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("未成年人不能注册!");
}
System.out.println("注册成功!");
}

public static void main(String[] args) {
checkAge(15); // 这里会抛出异常
}
}

执行结果:

1
Exception in thread "main" java.lang.IllegalArgumentException: 未成年人不能注册!

👉 作用:age < 18 时,我们主动抛出 IllegalArgumentException,让程序停止执行,并告诉调用者年龄不符合要求


2. 避免错误值继续传播

假设我们有一个计算方法,但输入不能是负数,否则计算就没有意义:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MathUtil {
public static int sqrt(int num) {
if (num < 0) {
throw new ArithmeticException("负数不能开平方!");
}
return (int) Math.sqrt(num);
}

public static void main(String[] args) {
System.out.println(sqrt(-9)); // 抛出异常
}
}

执行结果:

1
2
Exception in thread "main" java.lang.ArithmeticException: 负数不能开平方!

👉 作用: 这里如果不加 throwMath.sqrt(-9) 可能会返回 NaN,影响计算结果。主动抛异常可以阻止错误继续传播,让调用者知道数据不合法。


3. 在 catch 里重新抛出异常

有时候,程序捕获异常后,仍然希望把异常抛出去,让上层代码处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ReThrowExample {
public static void divide(int a, int b) {
try {
int result = a / b;
} catch (ArithmeticException e) {
System.out.println("捕获异常,但继续抛出");
throw e; // 重新抛出异常
}
}

public static void main(String[] args) {
divide(10, 0); // 这里最终仍然会抛出异常
}
}

执行结果:

1
2
3
捕获异常,但继续抛出
Exception in thread "main" java.lang.ArithmeticException: / by zero

👉 作用:catch 里先记录日志,然后再用 throw 重新抛出异常,让外部调用者知道出错了。


4. 抛出自定义异常

如果 Java 自带的异常不够用,我们可以自己定义异常,并在 throw 里使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MyException extends Exception {
public MyException(String message) {
super(message);
}
}

public class CustomThrowExample {
public static void checkValue(int value) throws MyException {
if (value > 100) {
throw new MyException("数值不能大于 100!");
}
}

public static void main(String[] args) {
try {
checkValue(150);
} catch (MyException e) {
System.out.println("自定义异常捕获:" + e.getMessage());
}
}
}

执行结果:

1
自定义异常捕获:数值不能大于 100

2. throws 关键字

throws 用于声明方法可能抛出的异常,让调用者知道这个方法可能会抛出异常。

语法:

1
返回类型 方法名(...) throws 异常类型1, 异常类型2 {     // 可能会抛出异常的代码 }`

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ThrowsExample {     
public static void readFile(String filePath) throws FileNotFoundException {
File file = new File(filePath);
Scanner scanner = new Scanner(file); // 可能抛出 FileNotFoundException
}
public static void main(String[] args) {
try {
readFile("test.txt");
} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e.getMessage());
}
}
}

3. try-catch 捕获异常

try-catch 语句用于捕获异常,并在 catch 块中处理异常,而不会导致程序终止。

语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
try {     
// 可能发生异常的代码
} catch (异常类型 变量) {
// 处理异常
}
````

**示例:**

java

复制编辑

`public class TryCatchExample { public static void main(String[] args) { try { int result = 10 / 0; // 可能抛出 ArithmeticException } catch (ArithmeticException e) { System.out.println("发生异常: " + e.getMessage()); } } }`

---

## 4. `try-with-resources`(最新 Java 处理方式)

Java 7 引入了 **try-with-resources**,用于自动关闭实现 `AutoCloseable` 接口的资源(如文件、网络连接)。

### 语法:

```Java
try (资源声明) {
// 使用资源的代码
} catch (异常类型 变量) {
// 处理异常
}

示例(自动关闭文件流):

1
2
3
4
5
6
7
8
9
10
11
import java.io.*;  
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
System.out.println(reader.readLine());
} catch (IOException e) {
System.out.println("读取文件时发生错误: " + e.getMessage());
}
}
}

try 块结束后,BufferedReader 会自动关闭,无需手动调用 close()


5. finally 语句

finally 块用于确保无论是否发生异常,都要执行的代码(例如资源释放)。

示例:

1
2
3
4
5
6
7
8
9
10
11
public class FinallyExample {     
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("发生异常: " + e.getMessage());
} finally {
System.out.println("程序执行结束!");
}
}
}

即使发生异常,finally 依然会执行 "程序执行结束!"


6. 自定义异常

如果 Java 现有异常类不能满足需求,可以自定义异常类(继承 ExceptionRuntimeException)。

受检异常(必须 throws 处理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}

public class CustomExceptionExample {
public static void validate(int num) throws MyCheckedException {
if (num < 0) {
throw new MyCheckedException("数字不能为负数!");
}
}

public static void main(String[] args) {
try {
validate(-5);
} catch (MyCheckedException e) {
System.out.println("捕获异常: " + e.getMessage());
}
}
}

运行时异常(可选 throws 处理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MyRuntimeException extends RuntimeException {
public MyRuntimeException(String message) {
super(message);
}
}

public class CustomRuntimeExceptionExample {
public static void validate(int num) {
if (num < 0) {
throw new MyRuntimeException("数字不能为负数!");
}
}

public static void main(String[] args) {
validate(-5); // 直接抛出异常
}
}

运行时异常不强制 throws 处理。


7. 最新 Java 异常处理改进(Java 9+)

1. try-with-resources 资源管理改进

在 Java 9 之前,try-with-resources 只能在 try(资源) 中声明新资源;从 Java 9 开始,可以在 try 之外声明资源,然后在 try 语句中使用。

Java 9+ 示例:

1
2
3
4
5
6
7
BufferedReader reader = new BufferedReader(new FileReader("test.txt"));
try (reader) { // 这里 reader 仍然会自动关闭
System.out.println(reader.readLine());
} catch (IOException e) {
System.out.println("读取文件时发生错误: " + e.getMessage());
}

2. 多异常捕获(Java 7+)

可以在一个 catch 块中捕获多个异常类型,提高代码简洁性。

示例:

1
2
3
4
5
6
try {
int num = Integer.parseInt("abc");
} catch (NumberFormatException | NullPointerException e) {
System.out.println("发生异常: " + e.getMessage());
}


总结

关键字 作用
throw 手动抛出异常
throws 声明方法可能抛出的异常
try-catch 捕获并处理异常
finally 无论异常是否发生,都会执行
try-with-resources 自动关闭资源(Java 7+)
多异常捕获 一个 catch 处理多个异常(Java 7+)

异常类

Java里面每个类都定义了异常类
所有的类都是Throwable的子类

Throwable派生了两个类

  • Error (IOError, LinkageError)
  • Exception (RuntimeError, 其他子类)

使用原则

  • 在当前方法声明使用try-catch语句捕获异常
  • 一个方法被覆盖时候,覆盖他的方法必须抛出相同的异常或者异常的子类
  • 如果父类抛出多个异常,则覆盖他的方法必须抛出那些异常的一个子集,不能抛出新的异常。