💜 想真正擅长编程? 从一门课程开始,100% 免费

3-8、常见异常汇总

把开发中最常见的异常整理在一起,按异常类型分类,附上原因和解决方案。遇到报错先来这里查,比百度快。


一、NullPointerException(空指针异常)

报错信息

TEXT
java.lang.NullPointerException

或Java 14+:

TEXT
java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null

常见原因

Java
// 1. 对null对象调用方法
String str = null;
str.length();  // 报错

// 2. 对null集合操作
List<String> list = null;
list.size();  // 报错

// 3. 从Map取值没判空
Map<String, Object> map = new HashMap<>();
String value = (String) map.get("key");
value.length();  // key不存在,返回null

// 4. 依赖注入失败
@Autowired
private UserService userService;  // userService为null

解决方案

Java
// 方案1:if判空
if (str != null) {
    str.length();
}

// 方案2:Optional
Optional.ofNullable(str)
    .map(String::length)
    .orElse(0);

// 方案3:StringUtils(Apache Commons Lang)
if (StringUtils.isNotEmpty(str)) {
    str.length();
}

// 方案4:集合判空
if (list != null && !list.isEmpty()) {
    list.size();
}

// 或用CollectionUtils
if (CollectionUtils.isNotEmpty(list)) {
    list.size();
}

二、ClassCastException(类型转换异常)

报错信息

TEXT
java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer

常见原因

Java
// 1. 从Map/Redis取值强转
Object obj = map.get("age");
Integer age = (Integer) obj;  // obj实际是String "25"

// 2. 从JSON解析强转
Object obj = JSON.parse(jsonStr);
List<User> list = (List<User>) obj;  // obj实际是JSONObject

解决方案

Java
// 方案1:用instanceof判断
if (obj instanceof Integer) {
    Integer age = (Integer) obj;
}

// 方案2:用String.valueOf转成String再解析
String str = String.valueOf(obj);
Integer age = Integer.parseInt(str);

// 方案3:用类型安全的JSON解析
List<User> list = JSON.parseArray(jsonStr, User.class);
User user = JSON.parseObject(jsonStr, User.class);

// 方案4:泛型
Map<String, Object> map = new HashMap<>();
// 取值时用String.valueOf,不要强转
String value = String.valueOf(map.get("key"));

三、NumberFormatException(数字格式异常)

报错信息

TEXT
java.lang.NumberFormatException: For input string: "abc"

常见原因

Java
// 字符串不是数字,但用parseInt转换
String str = "abc";
int num = Integer.parseInt(str);  // 报错

// 从前端传来的参数不是数字
String pageStr = request.getParameter("page");
int page = Integer.parseInt(pageStr);  // 如果pageStr是null或非数字

解决方案

Java
// 方案1:try-catch
try {
    int num = Integer.parseInt(str);
} catch (NumberFormatException e) {
    num = 0;  // 默认值
}

// 方案2:用StringUtils判断
if (StringUtils.isNumeric(str)) {
    int num = Integer.parseInt(str);
}

// 方案3:用NumberUtils(Apache Commons Lang)
int num = NumberUtils.toInt(str, 0);  // 转不了返回默认值0

四、SQLException(SQL异常)

报错信息1:表不存在

TEXT
java.sql.SQLSyntaxErrorException: Table 'my_project.user' doesn't exist

解决: 检查表名是否正确,表是否已创建。

报错信息2:字段不存在

TEXT
java.sql.SQLSyntaxErrorException: Unknown column 'user_name' in 'field list'

解决: 检查SQL语句里的字段名和数据库表字段名是否一致,注意大小写。

报错信息3:数据太长

TEXT
java.sql.SQLException: Data too long for column 'name' at row 1

解决: 检查数据长度是否超过字段定义,修改字段长度:

SQL
ALTER TABLE user MODIFY COLUMN name VARCHAR(255);

报错信息4:重复键

TEXT
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'admin' for key 'uk_username'

解决: 唯一索引冲突,数据已存在。先查是否存在再插入,或用INSERT ... ON DUPLICATE KEY UPDATE。

报错信息5:外键约束

TEXT
java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row:
a foreign key constraint fails

解决: 先删除子表数据,再删除父表数据。


五、IllegalArgumentException(非法参数异常)

报错信息

TEXT
java.lang.IllegalArgumentException: Source must not be null

常见原因

Java
// 1. BeanUtils.copyProperties源对象为null
BeanUtils.copyProperties(null, target);  // 报错

// 2. 参数校验失败
public void process(String name) {
    Assert.notNull(name, "name不能为空");
}

解决方案

Java
// 1. 判空后再操作
if (source != null) {
    BeanUtils.copyProperties(source, target);
}

// 2. 用Optional
Optional.ofNullable(source)
    .ifPresent(s -> BeanUtils.copyProperties(s, target));

// 3. 用Spring的@Validated参数校验
@PostMapping("/add")
public Result add(@Validated @RequestBody UserDTO dto) {
    // 如果dto字段不符合规则,自动返回400
}

六、IOException(IO异常)

报错信息1:文件找不到

TEXT
java.io.FileNotFoundException: class path resource [application.yml] cannot be opened

解决: 检查配置文件是否存在,是否在src/main/resources/目录下。

报错信息2:文件读取失败

TEXT
java.io.IOException: Stream Closed

解决: 检查流是否在使用前关闭,用try-with-resources:

Java
try (InputStream is = new FileInputStream("file.txt")) {
    // 使用流
} catch (IOException e) {
    log.error("读取文件失败", e);
}
// 流自动关闭,不需要手动close

七、ConcurrentModificationException(并发修改异常)

报错信息

TEXT
java.util.ConcurrentModificationException

常见原因

Java
// 遍历集合时同时修改集合
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
for (String item : list) {
    if ("b".equals(item)) {
        list.remove(item);  // 报错!
    }
}

解决方案

Java
// 方案1:用Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if ("b".equals(it.next())) {
        it.remove();  // 用Iterator的remove方法
    }
}

// 方案2:用removeIf
list.removeIf("b"::equals);

// 方案3:用CopyOnWriteArrayList(线程安全)
List<String> list = new CopyOnWriteArrayList<>(Arrays.asList("a", "b", "c"));

八、StackOverflowError(栈溢出)

报错信息

TEXT
java.lang.StackOverflowError: null

常见原因

Java
// 1. 无限递归
public int factorial(int n) {
    return n * factorial(n - 1);  // 没有终止条件
}

// 2. 循环依赖
// A类的构造方法new B,B类的构造方法new A

解决方案

Java
// 1. 递归加终止条件
public int factorial(int n) {
    if (n <= 1) return 1;  // 终止条件
    return n * factorial(n - 1);
}

// 2. 检查循环依赖,用@Autowired代替手动new

九、OutOfMemoryError(内存溢出)

报错信息1:Java堆空间

TEXT
java.lang.OutOfMemoryError: Java heap space

原因: 内存不够用,可能是加载了太多数据。

解决:

  1. 增大JVM内存:-Xmx2048m
  2. 分页查询,别一次性查所有数据
  3. 检查有没有内存泄漏

报错信息2:GC开销超限

TEXT
java.lang.OutOfMemoryError: GC overhead limit exceeded

原因: 垃圾回收花了太多时间但回收不了多少。

解决:

  1. 增大内存
  2. 检查有没有内存泄漏
  3. 用JProfiler/MAT分析内存

报错信息3:元空间

TEXT
java.lang.OutOfMemoryError: Metaspace

原因: 类元数据太多,可能是类加载器泄漏。

解决: 增大元空间:-XX:MaxMetaspaceSize=256m


十、Spring相关异常

1. Bean创建失败

TEXT
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'userService'

排查: 看Caused by部分,常见原因:

  • 依赖注入失败(找不到Bean)
  • 构造方法抛异常
  • @Value配置缺失

2. 循环依赖

TEXT
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'serviceA': Requested bean is currently in creation

原因: A依赖B,B依赖A,形成循环。

解决:

  • 用@Lazy注解延迟加载
  • 重构代码,消除循环依赖
  • SpringBoot 2.6+默认禁止循环依赖,可以开启:spring.main.allow-circular-references=true

3. 找不到Bean

TEXT
NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.UserService' available

解决:

  • 确认类上有@Service、@Component等注解
  • 确认包扫描路径正确
  • 确认@Autowired的接口有实现类

4. 配置绑定失败

TEXT
BindException: Failed to bind properties under 'spring.datasource' to ...

解决: 检查yml/properties配置项的类型和格式是否正确。


十一、MyBatis异常

1. 绑定异常

TEXT
org.apache.ibatis.binding.BindingException:
Invalid bound statement (not found): com.example.mapper.UserMapper.selectList

原因: Mapper接口和XML文件没对应上。

解决:

  • 检查XML文件里的namespace和Mapper接口全路径是否一致
  • 检查方法名和XML里的id是否一致
  • 检查mapper-locations配置是否正确

2. 参数绑定异常

TEXT
org.apache.ibatis.binding.BindingException:
Parameter 'userId' not found. Available parameters are [arg0, param1]

原因: Mapper方法参数没加@Param注解。

解决:

Java
// 错误
List<User> selectByCondition(String name, Integer age);

// 正确
List<User> selectByCondition(@Param("name") String name, @Param("age") Integer age);

十二、JSON序列化异常

1. 循环引用

TEXT
com.fasterxml.jackson.databind.JsonMappingException:
Infinite recursion (StackOverflowError)

原因: 对象之间相互引用,序列化时无限递归。

解决:

Java
// 加 @JsonIgnore 忽略反向引用
@JsonIgnore
private Order order;  // User类里引用Order,Order类里引用User

// 或用 @JsonManagedReference / @JsonBackReference
@JsonManagedReference
private List<User> users;  // 一方

@JsonBackReference
private Department department;  // 多方

2. 日期格式

TEXT
Cannot deserialize value of type `java.util.Date` from String "2026-01-01"

解决:

Java
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
private Date birthday;

3. 未知属性

TEXT
UnrecognizedPropertyException: Unrecognized field "xxx"

原因: JSON里有字段但Java类里没有对应属性。

解决:

Java
// 忽略未知属性
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserDTO { ... }

或全局配置:

YAML
spring:
  jackson:
    deserialization:
      fail-on-unknown-properties: false

十三、快速排查对照表

异常 根因 快速解决
NullPointerException 对象为null 判空 + Optional
ClassCastException 类型转换错 instanceof判断
NumberFormatException 字符串不是数字 NumberUtils
SQLException SQL有问题 看SQL日志
IllegalArgumentException 参数不合法 参数校验
ConcurrentModificationException 遍历时修改 Iterator/removeIf
StackOverflowError 无限递归/循环依赖 加终止条件
OutOfMemoryError 内存不足 增大内存/分页查询
BeanCreationException Bean创建失败 看Caused by
BindingException Mapper绑定失败 检查namespace和id
JsonMappingException JSON序列化失败 @JsonIgnore/@JsonFormat

小结

遇到异常别慌,按这个流程走:

  1. 看异常名 — 大概知道什么类型的问题
  2. 看异常消息 — 具体哪个变量/哪个表/哪个类
  3. 看堆栈 — 找com.公司名开头的行,定位到你的代码
  4. 打断点 — 在报错位置打断点,调试看变量值
  5. 查文档 — 百度/Google异常信息,大概率有人遇到过

把异常信息复制到搜索引擎搜,90%的问题都能找到解决方案。