包装类(如Long、Double)精度固定且不可突破,无法替代BigDecimal;Long整数溢出抛异常,Double超2⁵³后整数精度丢失;BigDecimal以字符串构建、可控精度与舍入,适合金额等高精度场景。

包装类(如 Long、Double)不是为高精度数值计算设计的,它们有明确且不可突破的精度边界。理解这一点的关键,不在于“怎么用包装类做高精度计算”,而在于认清:它们根本不能替代 BigDecimal,因为底层机制和设计目标完全不同。
包装类的精度边界是硬性限制,不是配置问题
Long 是 64 位有符号整数,最大值固定为 9,223,372,036,854,775,807。超出即溢出——Long.parseLong() 直接抛异常,这是它在“守界”,不是在“计算”。Double 虽能表示极大范围(±1.8×10³⁰⁸),但其整数精度上限是 2⁵³(约 9×10¹⁵)。超过这个值,相邻可表示整数的间隔大于 1,意味着很多整数根本无法被精确存储,例如:
-
Double.valueOf("9007199254740993")返回9007199254740992.0,末位静默丢失 - 这种截断不报错、不警告,只在业务结果中悄悄出错
BigDecimal 的“精度”是可控的,而包装类的“精度”是固定的
BigDecimal 的核心能力是“按需指定精度与舍入方式”。它以字符串或整数+标度(scale)形式存储数值,避免了二进制浮点表示的固有缺陷。这意味着:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 它可以精确表示
"0.1"、"12345678901234567890.0123456789"这类十进制小数 - 加减乘除运算可设定保留几位小数、用哪种舍入模式(如
RoundingMode.HALF_UP) - 除法即使遇到无限循环小数(如 1 ÷ 3),也能通过指定 scale 和 roundingMode 得到确定结果
包装类参与运算时会隐式引入误差链,BigDecimal 则全程显式可控
一旦把原始数据塞进 Double 或通过 new BigDecimal(double) 构造,精度损失就已发生。后续任何操作都基于这个失真值:
立即学习“Java免费学习笔记(深入)”;
-
double d = 0.1 + 0.2;→d已是0.30000000000000004 -
new BigDecimal(d)只是把那个错误的 double 值“忠实地转成 BigDecimal”,不会修复它 - 正确做法是:
new BigDecimal("0.1").add(new BigDecimal("0.2")),全程保持十进制精确性
业务关键字段必须绕过包装类,直连 BigDecimal 或 BigInteger
用户 ID、订单号、金额、税率、时间戳毫秒值等,只要要求“绝对精确”,就不能经过 Double 或 Long 中转:
- ID/订单号超 19 位?别用
Long解析,改用BigInteger或直接字符串处理 - 金额含小数?跳过
double字段,前端传字符串,后端用BigDecimal(String)构造 - 比较两个金额是否相等?用
a.compareTo(b) == 0,而非equals()(后者还校验小数位数)

















