【问题标题】:Promotion in Java?在 Java 中推广?
【发布时间】:2010-12-12 06:19:33
【问题描述】:

提升的规则是“当操作数属于不同类型时,自动二进制数字提升发生,较小的操作数类型转换为较大的操作数类型”。但是操作数是相同类型的,例如,

byte=byte+byte // Compile time error... found int..

那为什么会这样呢?

【问题讨论】:

标签: java


【解决方案1】:

要理解这一点,您应该参考两件事:

隐式转换: byte(8 位)-> short(16 位)-> int(32 位)-> float(32 位)-> double(64 位) char(16 位)-> int(32 位)

算术运算符规则

  1. 运算符优先级规则:此规则规定将首先评估 (*,/, %) 组。然后将评估 (+,-) 运算符的组。从同一组算子中,从左算起。

  2. 操作数提升规则:该规则规定数据类型小于 int 的操作数将被提升为 int。提升顺序(byte->short->int, char->int)

  3. 相同类型的操作数规则:此规则规定,如果两个操作数都是 int、long、float、double,则将相同的类型传递给结果类型。 即 long+long => long , float + float => float, int+int => int

  4. 混合类型操作数规则:如果有任何操作数来自上述顺序,则按照提升顺序 (int->long->float->double),则较小的将提升为较大的并结果将以更大的类型计算。 即 long + double => double , int + long => long

【讨论】:

    【解决方案2】:

    我想谈谈一般的促销

    Java 只能计算操作数类型相同的算术表达式

    例如,在包含 int 和 double 值的表达式中,int 值被提升为 double 值以便在表达式中使用。

    换个说法

    double someVar = 1 / 2;// someVar = 0
    

    但是

    double someVar = (double)1 / 2;// someVar = 0.5
    

    为什么?

    • 我们使用(双)cast operator 创建一个temporary 其操作数 "1" 的浮点副本(称为 explicit conversion)
    • 计算现在包括一个浮点值(1 的临时双副本)除以整数 2
    • 根据上面的说法,Java执行了一个叫做promotion的操作(或隐式转换),所以int values被提升为double values以使用in表达式=>整数2被提升为double
    • 表达式变为double someVar = 1.0 / 2.0; // someVar= 0.5

    希望这是有帮助的,即使它超出了问题的核心

    【讨论】:

      【解决方案3】:

      由于+算术运算符,来自this SO question和以上答案,两个操作数都转换为int类型。

      byte b1 = 1;
      byte b2 = 2;
      byte b3 = b1 + b2; // compile time error
      

      在上述代码中,b1 和 b2 的值将在运行时解析,因此编译器会在解析值之前将两者都转换为 int。

      但是如果我们考虑下面的代码,

      final byte b1 = 1;
      final byte b2 = 2;
      int b3 = b1 + b2; // constant expression, value resolved at compile time
      

      b1 和 b2 是最终变量,值将在编译时解析,因此编译不会失败。

      【讨论】:

        【解决方案4】:

        为您提供了有关自动提升为“int”的正确答案。

        关于这一点还有一个注意事项 - 复合赋值运算符的行为就像它们具有隐式类型大小写一样。示例:

        byte b1 = 1;
        byte b2 = 2;
        b1 = b1 + b2; // compilation fails
        b1 += b2; // compilation successful
        

        【讨论】:

          【解决方案5】:

          byte 没有 + 运算符。相反,两个操作数都被提升为 int,所以你有

          byte = byte + byte
          ... becomes (widening to find + operator) ...
          byte = int + int
          ... becomes (result of + operator) ...
          byte = int 
          

          ... 然后失败,因为没有从 int 到 byte 的隐式转换。你需要投射:

          byte a = 1;
          byte b = 2;
          
          byte c = (byte) (a + b);
          

          以下是数字提升的实际规则,来自section 5.6.2 of the JLS:


          当运算符对一对操作数应用二进制数字提升时,每个操作数都必须表示一个可转换为数字类型的值,以下规则依次适用,使用扩展转换(第 5.1.2 节)进行转换必要的操作数:

          • 如果任何操作数属于引用类型,则会执行拆箱转换(第 5.1.8 节)。然后:
          • 如果任一操作数为 double 类型,则另一个将转换为 double。
          • 否则,如果任一操作数为浮点类型,则将另一个转换为浮点类型。
          • 否则,如果任一操作数为 long 类型,则将另一个转换为 long。
          • 否则,两个操作数都将转换为 int 类型。

          【讨论】:

          • 感谢乔恩这是我所期望的。但我要问的一件事是,为什么字节没有 + 运算符?
          • 恕我直言,如果是这种情况,那么为什么短 + 短不起作用。我相信算术运算符有一些规则:其中之一是操作数提升规则:“任何小于 int 的操作数都将提升为 int”
          • @NavdeepSingh: short = short + short 不起作用,原因与此答案中已经解释的完全相同。两个操作数都被提升为 int。
          猜你喜欢
          • 1970-01-01
          • 2020-09-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-26
          • 1970-01-01
          • 1970-01-01
          • 2013-11-05
          相关资源
          最近更新 更多