把开发中最常见的异常整理在一起,按异常类型分类,附上原因和解决方案。遇到报错先来这里查,比百度快。
一、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
原因: 内存不够用,可能是加载了太多数据。
解决:
- 增大JVM内存:
-Xmx2048m - 分页查询,别一次性查所有数据
- 检查有没有内存泄漏
报错信息2:GC开销超限
TEXT
java.lang.OutOfMemoryError: GC overhead limit exceeded
原因: 垃圾回收花了太多时间但回收不了多少。
解决:
- 增大内存
- 检查有没有内存泄漏
- 用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 |
小结
遇到异常别慌,按这个流程走:
- 看异常名 — 大概知道什么类型的问题
- 看异常消息 — 具体哪个变量/哪个表/哪个类
- 看堆栈 — 找
com.公司名开头的行,定位到你的代码 - 打断点 — 在报错位置打断点,调试看变量值
- 查文档 — 百度/Google异常信息,大概率有人遇到过
把异常信息复制到搜索引擎搜,90%的问题都能找到解决方案。