一、场景引入:为什么你的数据库类型会报错?
在Java开发中,你是否遇到过这样的报错:ClassCastException: java.lang.Long cannot be cast to java.math.BigInteger
?或者明明数据库的BIGINT
字段能存储大数,Java程序却出现数值溢出?这背后其实隐藏着BigInteger与Long的核心差异。本文将通过3分钟快速解读,让你彻底掌握两者的区别,并解决数据库字段类型映射的选型难题。
二、BigInteger vs Long:核心差异对比
1. 数值范围
Long:64位有符号整数,范围是 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807,超出范围会自动溢出导致结果错误。
BigInteger:任意精度整数,无固定范围限制(仅受内存限制),可精确计算超大数(如1000的阶乘)
示例对比:计算100的阶乘
用Long:直接溢出为负数
用BigInteger:正确输出933262154439891732384626...(共158位)
2. 性能与存储方式的差异
特性 | Long | BigInteger |
存储方式 | 栈内存直接存储(8字节) | 堆内存对象(动态int数组) |
运算速度 | 快(CPU原生支持) | 慢(需模拟大数运算) |
运算符支持 | 支持 | 必须调用 |
三、数据库BIGINT
字段选型指南
1. 必须选Long的情况
当数据库字段为 BIGINT
(有符号) 时,其范围与Java的Long完全一致。此时优先使用Long,性能更高且无转换问题。
MyBatis映射示例:
public class User {
private Long id; // 对应数据库BIGINT字段
}
2. 必须选BigInteger的情况
当数据库字段为 BIGINT UNSIGNED
(无符号) 时,其范围是 0 ~ 18,446,744,073,709,551,615,超过Long的正数上限。此时必须用BigInteger,否则会溢出或转换异常。
错误示范:
// 错误!BIGINT UNSIGNED超过Long范围
private Long id;
// 正确写法:
private BigInteger id;
四、开发避坑指南
1. ORM框架映射规则
- MyBatis/MyBatis-Plus:根据数据库字段符号类型自动映射:
BIGINT
→Long
BIGINT UNSIGNED
→BigInteger
强制类型错误:若用Long接收无符号BIGINT,会触发ClassCastException
2. 性能优化建议
避免滥用BigInteger:仅在大数计算时使用,常规场景用Long效率提升百倍
- 数值边界检查:通过
DESCRIBE
命令确认数据库字段是否为无符号:
DESCRIBE your_table; -- 查看字段是否有UNSIGNED标识
五、总结对比表
对比维度 | Long | BigInteger |
范围 | -9,223,372,036,854,775,808 至 9,223,372,036,854,775,807 | 无限(受内存限制) |
性能 | 快 | 慢 |
溢出处理 | 自动回绕(可能导致错误) | 精确计算无溢出 |
适用场景 | 时间戳、常规ID | 加密算法、科学计算、超大数 |
数据库映射 | BIGINT(有符号) | BIGINT UNSIGNED |
六、实战口诀
“有符号选Long,无符号用BigInteger;性能优先看场景,超大计算不犹豫”。合理选择类型,既能避免程序崩溃,又能提升运行效率。