在Java的异常体系中,Exception是所有异常类的顶层父类,而RuntimeException是Exception的重要子类,两者在使用规则、适用场景上有明显差异,正确理解和使用它们能有效提升代码的容错性和可维护性。

Exception和RuntimeException的核心区别
Exception分为可检查异常(Checked Exception)和运行时异常(Unchecked Exception),其中RuntimeException及其子类都属于运行时异常,不需要强制处理,而Exception的其他子类属于可检查异常,必须按照Java语法要求处理。具体差异如下:
| 对比维度 | Exception(可检查异常子类) | RuntimeException |
|---|---|---|
| 处理要求 | 必须显式捕获或者通过throws声明抛出,否则编译报错 | 不强制捕获或声明,编译阶段不会报错 |
| 常见触发原因 | 外部环境导致的异常,如文件不存在、网络断开 | 程序逻辑错误,如空指针、数组越界、除零错误 |
| 典型子类 | IOException、SQLException、ClassNotFoundException | NullPointerException、IndexOutOfBoundsException、ArithmeticException |
Exception的使用方式
可检查异常通常用于处理那些即使开发者正确处理也可能出现的异常情况,比如读取文件时文件可能被删除,调用外部接口时可能网络不通。下面是一个读取文件内容时使用Exception的例子:
import java.io.FileInputStream;
import java.io.IOException;
public class ExceptionDemo {
public static void readFile(String filePath) throws IOException {
// 读取文件可能触发FileNotFoundException,属于Exception的子类
FileInputStream fis = new FileInputStream(filePath);
int content;
// 读取内容可能触发IOException
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
// 关闭流可能触发IOException
fis.close();
}
public static void main(String[] args) {
try {
readFile("test.txt");
} catch (IOException e) {
// 捕获异常后进行处理,比如打印日志或者给用户友好提示
System.out.println("文件读取失败,请检查文件路径是否正确");
e.printStackTrace();
}
}
}如果不在方法上声明throws IOException,也不在方法内部捕获异常,这段代码就会编译失败,这就是可检查异常的处理要求。
RuntimeException的使用方式
RuntimeException通常对应程序的逻辑错误,这类异常应该通过优化代码逻辑来避免,而不是依赖捕获处理。比如下面的除零操作就会触发ArithmeticException,它是RuntimeException的子类:
public class RuntimeExceptionDemo {
public static int divide(int a, int b) {
// 当b为0时,会抛出ArithmeticException,属于RuntimeException
return a / b;
}
public static void main(String[] args) {
// 可以不捕获运行时异常,编译不会报错
int result = divide(10, 0);
System.out.println(result);
}
}上面的代码编译不会报错,但运行时会抛出ArithmeticException,正确的做法是在方法内部提前判断除数是否为0,从逻辑上避免异常触发:
public class RuntimeExceptionDemo {
public static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("除数不能为0");
}
return a / b;
}
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
}
}自定义异常的选择
在实际开发中,我们常常需要自定义异常来满足业务需求,这时候需要选择继承Exception还是RuntimeException:
- 如果异常是业务层面的可预知异常,比如用户未登录、参数校验不通过,需要调用方必须处理,就继承Exception,作为可检查异常。
- 如果异常是由于调用方违反方法约定导致的逻辑错误,比如传入非法参数,不需要强制调用方处理,就继承RuntimeException。
下面是一个继承Exception的自定义业务异常示例:
// 自定义业务异常,继承Exception,属于可检查异常
public class BusinessException extends Exception {
private String errorCode;
public BusinessException(String message, String errorCode) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}
// 使用自定义异常
public class UserService {
public void login(String username, String password) throws BusinessException {
if (username == null || username.isEmpty()) {
throw new BusinessException("用户名不能为空", "10001");
}
if (password == null || password.isEmpty()) {
throw new BusinessException("密码不能为空", "10002");
}
// 登录逻辑
}
}总结来说,Exception(可检查异常)用于处理不可控的外部异常,要求调用方必须处理,RuntimeExcption用于处理程序逻辑错误,不需要强制处理。合理选择两者能让异常处理更清晰,代码更健壮。
JavaExceptionRuntimeException异常处理自定义异常修改时间:2026-06-06 06:19:25