Java中大数字不能用基本类型安全存储,因会静默溢出;超long范围用BigInteger,精确小数用BigDecimal,稍大但不超long优先用long,构造时须用字符串避免精度丢失。

Java 中大数字不能用基本类型安全存储。
基本类型(byte、short、int、long)都有固定位数和确定范围。例如:
-
int最大值是 2,147,483,647(约 21 亿) -
long最大值是 9,223,372,036,854,775,807(约 922 亿亿)
一旦数字超出对应类型的上限,就会发生静默溢出:结果不是报错,而是变成一个完全错误的数值(比如正数变负数),且编译器通常不警告——除非你在赋值字面量时明显越界(如 int x = 3000000000; 会直接编译失败)。
所以,“用基本类型存储大数字”本质上是个伪命题——你只能在数字确定不超限时才用基本类型。一旦不确定或已知会超限,就必须换方案。
立即学习“Java免费学习笔记(深入)”;
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
✅ 正确做法:按场景选替代方案
1. 超出 long 范围的大整数 → 用 BigInteger
它不占固定内存,大小只受限于堆空间,支持任意精度整数运算:
BigInteger big = new BigInteger("123456789012345678901234567890");
BigInteger result = big.multiply(BigInteger.TEN).add(BigInteger.ONE);⚠️ 注意:
- 必须用字符串或
valueOf(long)构造,避免new BigInteger(123456789012345678901234567890L)(字面量本身已溢出) - 不支持
+ - * /运算符,必须调用.add()、.multiply()等方法 - 比较用
.equals()或.compareTo() == 0,别用==
2. 需要精确小数(如金额)→ 用 BigDecimalfloat/double 有二进制精度问题(0.1 + 0.2 != 0.3),而 BigDecimal 可控精度:
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal sum = a.add(b); // 结果精确为 "0.3"⚠️ 关键细节:
- 构造必须用字符串,禁用
new BigDecimal(0.1)(0.1在double中本就不精确) -
divide()必须指定精度和舍入模式,否则可能抛ArithmeticException - 输出推荐
toPlainString(),避免科学计数法
3. 稍大但仍在 long 范围内 → 优先升级到 long
比如时间戳、订单号、大计数器等,声明时加 L 后缀:
long orderId = 1234567890123456789L; // ✅ 合法 // int orderId = 1234567890123456789; // ❌ 编译失败
❌ 常见错误写法(务必避开)
-
BigInteger n = 12345678901234567890L;→ 编译不通过(不能直接赋值基本类型字面量) -
BigDecimal price = new BigDecimal(19.99);→ 实际存的是19.990000000000002(精度污染) -
if (a == b)比较两个BigInteger→ 比的是引用,不是数值 -
a.divide(b)不设精度 →1/3会无限循环,抛异常
不复杂但容易忽略。

















