Java基本类型转换本质是二进制位的重新解释或截断,非数学无损映射;小转大(如byte→int、float→double)通常无损,大转小(如double→int、long→byte)必然或可能丢失精度,须用Math.toIntExact等主动校验防控。

基本数据类型之间的转换无法“保证”精度,只能通过合理选型、规避高危操作和主动校验来最大限度减少或暴露精度损失。Java 中的类型转换本质是位模式的重新解释或截断,不是数学意义上的无损映射。
一、哪些转换天然无损?
以下情况一般不会丢失精度:
-
小范围整型 → 大范围整型:如
byte → int、short → long、int → long,数值范围完全被覆盖,位数增加不丢信息 - float → double:double 有效位(约15–17位)远超 float(约6–7位),可精确表示所有 float 值
- char → int(且值在 0–65535 内):char 是无符号16位整数,转为 int 仅高位补零,无信息损失
二、哪些转换必然或可能丢失精度?
这些是高频出错点,需特别警惕:
-
浮点 → 整型:如
(int)3.9得3,(long)1e10若超出 long 范围,结果为Long.MAX_VALUE或Long.MIN_VALUE(静默溢出) - double → float:因有效位骤减,123456789.123456789 存为 double 精确,转 float 后常变成 123456792.0
-
大整型 → 小整型:如
long → byte只保留低8位,257变成1,-129变成127 -
整型字面量参与运算时的隐式提升:
byte a = 100; byte b = 50; byte c = a + b;编译失败——因为a + b自动提升为int,必须写成byte c = (byte)(a + b);,此时已发生潜在截断
三、怎么主动防控精度问题?
靠编译器默认行为不行,得用工具和约定:
-
用
Math.toIntExact()替代裸强转:例如Math.toIntExact(3000000000L)直接抛ArithmeticException,让溢出从“静默错误”变成“明确失败” -
金融/计费场景一律用
BigDecimal:不要用double或float做金额计算,0.1 + 0.2 != 0.3是 IEEE 754 的固有特性 -
数据库映射严格对齐:tinyint 字段若存整数而非布尔,JDBC 连接串加
?tinyInt1isBit=false;decimal 字段必须对应BigDecimal,不能用double -
边界值测试写进单元测试:比如验证
(byte)128 == -128、(short)32768 == -32768,提前发现绕回逻辑是否符合业务预期
四、一个容易忽略的关键细节
char 和整型互转不是“字符编码转换”,而是纯数值映射:(char)65 是 'A',没问题;
但 (char)200000 实际等价于 (char)(200000 & 0xFFFF) = (char)34464,得到的是某个 Unicode 字符(可能不可见或非预期),不是“转错了”,而是设计如此。











