Java 中基元类型的强制转换规则

Casting rules for primitive types in java

提问人:overexchange 提问时间:6/11/2015 最后编辑:user207421overexchange 更新时间:7/4/2022 访问量:25392

问:

在 java 中,

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

有浮动类型(float/double)

有布尔 type(),而不是整数类型,不像 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?
    
Java 强制转换 基元类型

评论

6赞 dhke 6/11/2015
基元类型的规则实际上是明确说明的:docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2。用于加宽,docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3 用于变窄。
0赞 overexchange 6/11/2015
@dhke为什么和 -1 根据 5.1.3?有什么理由吗?(byte)fmax(short)fmax
1赞 faramir 7/15/2016
@overexchange - 一切都在那里解释:“结果可以通过检查最小值和最大值 int 的低阶位来理解。最小 int 为十六进制 0x80000000,最大 int 为 0x7fffffff。这解释了短结果,即这些值的低 16 位,即 0x0000 和 0xffff;它解释了 char 结果,这些结果也是这些值的低 16 位,即 '\u0000' 和 '\uffff';它解释了字节结果,即这些值的低 8 位,即 0x00 和 0xff。

答:

29赞 dhke 6/11/2015 #1

JLS 列表

19 对基元类型的特定转换称为扩展基元转换:

  • 字节转换为短整型、整数、长整型、浮点数或双精度
  • 短到整数、多头、浮点数或双精度
  • char 到 int、long、float 或 double
  • int 到 long、float 或 double
  • 长到浮动或双倍
  • 浮点数到双精度

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

其他一切都需要明确的演员阵容。缩小有点复杂:

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

例子:

int doubleToInt = (int)aDoubleValue; 

根据四舍五入规则的产量。Integer.MAX_VALUE

byte doubleToByte = (byte)aDoubleValue; 

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

short doubleToShort = (short)aDoubleValue;

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

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

可以看出,浮点和整数缩小操作是有区别的。浮点运算执行实际舍入,而整数运算执行按位箝位。

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