java强制类型转换需警惕溢出与截断:大转小会静默翻转,浮点转整型向零截断,引用类型转换须先判型,应优先使用math.tointexact等带溢出检查的api。

Java强制转换不是“加个括号就完事”,尤其从大范围类型(如double、long)转小范围类型(如int、short、byte)时,编译器不检查值是否越界,运行时也不会报错——它直接截断、丢精度或产生负数,结果往往出人意料。
基本转换要防溢出和截断
小范围类型有固定取值边界:byte是-128~127,short是-32768~32767,int是-2³¹~2³¹−1。超出就翻转,不是报错。
-
byte b = (byte) 200;→ 结果是-56(200对256取模再按补码解释) -
short s = (short) 32768;→ 结果是-32768 -
int i = (int) 3e9;→ 3000000000 > Integer.MAX_VALUE(2147483647),结果为-1294967296
浮点转整型:先想清楚要不要四舍五入
直接强转是向零截断:(int) 3.9得3,(int) -3.9得-3。若需四舍五入,必须显式调用Math.round(),但要注意round()返回long,仍可能溢出。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 安全截断:先用
Double.isFinite(d)排除NaN和无穷,再判断范围:d >= Integer.MIN_VALUE && d - 安全四舍五入:
long r = Math.round(d); int i = Math.toIntExact(r);(JDK 8+) - 别写
(int) Math.round(d)——万一round结果超int范围,会静默溢出
引用类型转换:类型匹配比精度更重要
泛型集合或JSON解析后常存的是Double或Long,直接(Integer) obj会抛ClassCastException,这不是精度问题,是类型不兼容。
- 永远先用
obj instanceof Number确认是数字类型 - 再根据实际包装类分发处理:
obj instanceof Double→ 走浮点校验;obj instanceof Long→ 用Math.toIntExact((Long)obj) - 推荐封装工具方法:
NumberUtils.toInt(Number n),内部统一做null检查、类型判断、范围校验
用带溢出检查的工具替代裸强转
JDK 提供了少数真正“安全”的转换入口,它们会在越界时明确抛异常,而不是返回错误值。
-
Math.toIntExact(long):只接受long,溢出抛ArithmeticException -
Math.floorDiv(int, int)等运算类方法也自带溢出防护 - 金融、配置解析等关键场景,应优先使用这些API,而非
(int)或(short) - 连
Integer.valueOf(String)都比裸强转多一层解析校验,而(int) someDouble连异常都不抛
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










