java类型转换的语义错误源于精度丢失和溢出,关键在于是否符合业务意图:浮点转整数需明确取整逻辑,高精度降级须校验范围,字符串解析必须用标准api,金融计算应全程使用bigdecimal。

Java 类型转换本身不报错,但精度丢失和数值溢出是运行时静默发生的语义错误——你写的代码合法,结果却不对。关键不是“能不能转”,而是“转得是否符合业务意图”。
浮点数转整数:别信(int)截断,要明确取整逻辑
直接写 (int)3.9 得到 3,(int)-3.9 得到 -3,这是向零截断,不是四舍五入,也不等价于“离最近整数更近”。多数业务场景需要的是数学意义上的四舍五入:
- 用
Math.round(double)(返回long)或Math.round(float)(返回int) - 若需转为
int且防溢出,改用Math.toIntExact(Math.round(d)),超范围直接抛ArithmeticException - 仅需丢弃小数部分?先确认业务是否真接受“砍掉”,而不是“向下取整”(
Math.floor)或“向零取整”(Math.trunc)
高精度整型降级:必须先校验,再转换
把 long 赋给 int、int 强转为 byte,编译器允许,但超出目标类型范围时会静默绕回。例如:
-
long id = 2147483648L;→(int)id结果是-2147483648,订单ID突变负数 -
int x = 200;→(byte)x得到-56(因byte范围是 -128~127)
安全做法:
- 显式范围检查:
if (value >= Integer.MIN_VALUE && value - 优先使用 JDK 内置方法:
Math.toIntExact(longValue)、Math.toShortExact(intValue) - 若允许饱和(溢出即取边界值),可用 Guava 的
Ints.saturatedCast(longValue)
字符串与数值互转:必须走标准 API,禁用硬转
Java 不支持 (int)"123" 这类写法。字符串解析失败会抛异常,不能靠强制转换兜底:
- 整数:
Integer.parseInt("123")(抛NumberFormatException)或Integer.valueOf("123")(返回Integer对象) - 浮点数:
Double.parseDouble("12.8"),但注意:它仍基于二进制浮点表示,"12.8"解析后仍是近似值 - 对精度敏感场景(如金额),应跳过
double中间层:new BigDecimal("12.8")或BigDecimal.valueOf("12.8")
浮点运算精度陷阱:用错类型,算得再快也没用
float 和 double 本质是二进制科学计数法,无法精确表示大多数十进制小数。常见误区:
-
float f = 12.8F;存的其实是12.800000190734863;再赋给double d = f;,只是复制这个近似值,不是“升级精度” -
0.1 + 0.2 == 0.3为false,这是 IEEE 754 标准的必然结果,不是 bug - 金融计算必须全程用
BigDecimal,单位建议用“分”代替“元”,避免小数位参与运算
比较浮点数时,禁用 ==,改用:Math.abs(a - b) ,或统一转 <code>BigDecimal 后调用 compareTo()。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











