java大范围向小范围强制转换会静默截断、丢精度或翻转符号:整数转仅保留低位字节,浮点转整型向零截断,引用类型需先判型再拆箱,应优先使用math.tointexact等带溢出检查的api。

Java 中大范围向小范围强制转换不是加个括号就完事,而是会静默截断、丢精度甚至翻转符号——编译不报错,运行也不抛异常,但结果可能完全不对。
整数类型间转换:只保留低位字节,溢出即翻转
比如 int 转 byte,Java 不做范围检查,直接取低 8 位,按补码解释:
-
byte b = (byte) 200;→ 结果是 -56(200 % 256 = -56) -
short s = (short) 32768;→ 结果是 -32768(超出 short 最大值 32767) -
int i = (int) 3_000_000_000L;→ 结果是 -1294967296(long 高位被丢弃)
浮点转整型:向零截断,不是四舍五入
直接强转会直接砍掉小数部分,且不校验是否越界:
-
(int) 3.9→ 3,(int) -3.9→ -3 -
(int) 3e10→ 得到负数(远超Integer.MAX_VALUE) - 若需四舍五入,应写:
Math.toIntExact(Math.round(d)),而不是(int) Math.round(d)
引用类型转基本类型:先判型,再拆箱
从 JSON 或泛型集合拿到的 Object 很可能是 Double 或 Long,不能直接 (Integer) obj:
- 必须先确认:
obj instanceof Number - 再分发处理:
obj instanceof Double→ 做浮点范围校验;obj instanceof Long→ 用Math.toIntExact((Long)obj) - 推荐封装工具方法,统一处理 null、类型、范围三重校验
安全替代方案:用带溢出检查的 API
裸强转风险高,关键场景应优先使用 JDK 提供的安全入口:
-
Math.toIntExact(long):越界时明确抛ArithmeticException -
Math.floorDiv(int, int)等运算方法也自带溢出防护 - 解析字符串数字时,
Integer.parseInt("123")比(int) Double.parseDouble("123")更可靠
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











