Java 中基元类型的转换规则

2022-09-02 10:01:45

在java中,

有积分类型(char/short/int/long/byte)

有浮动类型(float/double)

有布尔类型(),而不是整数类型,不像C语言。boolean

问题:

  1. 是否有转换的通用规则(根据JLS)可以讨论哪种类型可以转换为另一种类型?出于常识,我知道,积分和浮动类型是不允许的boolean

  2. 请帮我了解以下输出的原因:

         /*
          * Casting rules for primitive types
          */
         double aDoubleValue = 30000000000000000000.123438934;
         int doubleToInt = (int)aDoubleValue; //stores max value 2147483647, makes sense!!
         byte doubleToByte = (byte)aDoubleValue; //stores -1, why not 127?
         short doubleToShort = (short)aDoubleValue; // stores -1, why not 32767?
         long doubleToLong = (long)aDoubleValue; // stores 9223372036854775807, makes sense!!
         float doubleToFloat = (float)aDoubleValue; // stores 3.0E19, 3.0 x 10^19  max value of float
         char doubleToChar = (char)aDoubleValue; // what does this store?
    

答案 1

JLS 列表

基元类型的 19 个特定转换称为加宽基元转换:

  • 字节到短整型、整型、长整型、浮点型或双精度型
  • 短到整型、长整型、浮点型或双精度型
  • 字符到整型、长整型、浮动型或双精度型
  • 整型到长整型、浮点型或双精度型
  • 长至浮动或双倍
  • 浮点到双倍

请注意缺少的从 和 到 的转换,即使长度为两个字节。byteshortcharchar

其他所有内容都需要显式强制转换。缩小范围稍微复杂一些:

  • double以使用标准 IEEE 754 舍入。float
  • 整数值将其最高有效位剥离到目标类型的可用宽度。这可能会导致出现一个符号位,例如(byte)0xfff == (byte)-1;
  • 如果源类型是浮点型,而目标类型是 ,则通过舍入到零来转换该值。long
  • 如果源类型是浮点型,而目标类型是整数但不是整数,则该值首先通过舍入到零来转换为。然后,使用整数转换将结果转换为目标类型。longintint

例子:

int doubleToInt = (int)aDoubleValue; 

根据舍入规则产生。Integer.MAX_VALUE

byte doubleToByte = (byte)aDoubleValue; 

首先转换为 ,然后将其转换为 。 是 ,因此字节值为 。intInteger.MAX_VALUEbyteInteger.MAX_VALUE0x7fffffff0xff-1

short doubleToShort = (short)aDoubleValue;

同样:转换为 ,产生 。 到产量,即 .intInteger.MAX_VALUE0x7fffffffshort0xffff-1

棘手的事情实际上是转换。 是一个 16 位 unicode 字符,因此为您提供了现在熟悉的规则。charcharchar doubleToChar = (char)aDoubleValue'\uffff'

可以看出,浮点运算和整数缩小运算之间存在差异。浮点运算执行实际舍入,而整数运算执行按位钳位。

整数语义可能继承自 C。至少浮点到积分缩小操作的第一步也是你所期望的。第二个缩小步骤,从双倍/浮点到短,字节和字符可能看起来有点令人惊讶,但如果你真的将浮点数转换为短,你应该仔细检查你是否知道你在做什么。


答案 2

推荐