目录
宽化类型转换
转换规则
精度损失问题
补充说明
窄化类型转换
转换规则
精度损失问题
补充说明
宽化类型转换
转换规则
Java 虚拟机直接支持以下数值的宽化类型转换(widening numeric conversion, 小范围类型向大范围类型的安全转换)。也就是说,并不需要指令执行,包括:
● 从 int 类型到 long、 float 或者 double 类型。对应的指令为:i2l、i2f、i2d
● 从 long 类型到 float、double 类型。对应的指令为:l2f、l2d
● 从 float 类型到 double 类型。对应的指令为:f2d
简化为:int --> long --> float --> double
精度损失问题
宽化类型转换是不会因为超过目标类型最大值而丢失信息的,例如,从 int 转换到 long,或者从 int 转换到 double,都不会丢失任何信息,转换前后的值是精确相等的
从 int、 long 类型数值转换到 float,或者 long 类型数值转换到 double 时,将可能发生精度丢失一可能丢失掉几个最低有效位上的值,转换后的浮点数值是根据 IEEE754 最接近舍入模式所得到的正确整数值
尽管宽化类型转换实际上是可能发生精度丢失的,但是这种转换永远不会导致 Java 虚拟机抛出运行时异常
补充说明
从 byte、char 和 short 类型到 int 类型的宽化类型转换实际上是不存在的。对于 byte 类型转为 int,虚拟机并没有做实质性的转化处理,只是简单地通过操作数栈交换了两个数据。而将 byte 转为 long 时,使用的是 i2l,可以看到在内部 byte 在这里已经等同于 int 类型处理,类似的还有 short 类型
窄化类型转换
转换规则
Java 虚拟机也直接支持以下窄化类型转换:
● 从 int 类型至 byte、short 或者 char 类型。 对应的指令有:i2b、i2c、i2s
● 从 long 类型到 int 类型。对应的指令有:l2i
● 从 float 类型到 int 或者 long 类型。对应的指令有: f2i、 f2l
● 从 double 类型到 int、long 或者 float 类型。对应的指令有:d2i、 d2l、d2f
精度损失问题
窄化类型转换可能会导致转换结果具备不同的正负号、不同的数量级,因此,转换过程很可能会导致数值丢失精度
尽管数据类型窄化转换可能会发生上限溢出、下限溢出和精度丢失等情况,但是 Java 虛拟机规范中明确规定数值类型的窄化转换指令永远不可能导致虚拟机抛出运行时异常
补充说明
当将一个浮点值窄化转换为整数类型 T (T 限于 int 或 long 类型之一)的时候,将遵循以下转换规则:
如果浮点值是 NaN,那转换结果就是 int 或 long 类型的 0
如果浮点值不是无穷大的话,浮点值使用 IEEE754 的向零舍入模式取整,获得整数值 v,如果 v 在目标类型 T(int 或 long)的表示范围之内,那转换结果就是 v。否则,将根据 v 的符号,转换为 T 所能表示的最大或者最小正数
当将一个 double 类型窄化转换为 float 类型时,将遵循以下转换规则:
通过向最接近数舍入模式舍入一个可以使用 float 类型表示的数字。最后结果根据下面这 3 条规则判断:
如果转换结果的绝对值太小而无法使用 float 来表示, 将返回 float 类型的正负零
如果转换结果的绝对值太大而无法使用 float 来表示, 将返回 float 类型的正负无穷大
对于 double 类型的 NaN 值将按规定转换为 float 类型的 NaN 值