首页 文章

为什么要't Java' s =, - =,* =,/ =复合赋值运算符需要转换?

提问于
浏览
3435

直到今天,我还以为:

i += j;

只是一个捷径:

i = i + j;

但是如果我们试试这个:

int i = 5;
long j = 8;

然后 i = i + j; 将无法编译,但 i += j; 将编译正常 .

这是否意味着 i += j; 实际上是 i = (type of i) (i + j) 的快捷方式?

11 回答

  • 2314

    这个演员的一个很好的例子是使用* =或/ =

    byte b = 10;
    b *= 5.7;
    System.out.println(b); // prints 57
    

    要么

    byte b = 100;
    b /= 2.5;
    System.out.println(b); // prints 40
    

    要么

    char ch = '0';
    ch *= 1.1;
    System.out.println(ch); // prints '4'
    

    要么

    char ch = 'A';
    ch *= 1.5;
    System.out.println(ch); // prints 'a'
    
  • 178

    非常好的问题 . Java Language specification确认了您的建议 .

    例如,以下代码是正确的:short x = 3;
    x = 4.6;
    并且结果x的值为7,因为它相当于:short x = 3;
    x =(短)(x 4.6);

  • 42

    是,

    基本上我们写的时候

    i += l;
    

    编译器将其转换为

    i = (int)(i + l);
    

    我刚检查了 .class 文件代码 .

    真的是一件好事

  • 22

    你需要在 i = i + l 的情况下从 long 转换为 int explicitly 然后它将编译并提供正确的输出 . 喜欢

    i = i + (int)l;
    

    要么

    i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.
    

    但是在 += 的情况下它只是工作正常,因为运算符隐式地从右变量的类型到左变量的类型进行类型转换,因此不需要显式转换 .

  • 51

    一如既往地提出这些问题,JLS就是答案 . 在这种情况下§15.26.2 Compound Assignment Operators . 提取物:

    E1 op = E2形式的复合赋值表达式等效于E1 =(T)((E1)op(E2)),其中T是E1的类型,除了E1仅被评估一次 .

    引自§15.26.2的一个例子

    [...]以下代码是正确的:短x = 3;
    x = 4.6;
    并且结果x的值为7,因为它相当于:short x = 3;
    x =(短)(x 4.6);

    换句话说,你的假设是正确的 .

  • 462

    这里的问题涉及类型铸造 .

    当你添加int和long时,

    • int对象被转换为long并且两者都被添加并且你获得了长对象 .

    • 但长对象不能隐式转换为int . 所以,你必须明确地这样做 .

    但是 += 的编码方式是它可以进行类型转换 . i=(int)(i+m)

  • 238

    在Java类型中,当赋值操作右侧的表达式类型可以安全地提升为赋值左侧的变量类型时,将自动执行转换 . 因此我们可以安全地分配:

    byte -> short -> int -> long -> float -> double.
    

    反之亦然 . 例如,我们不能自动将long转换为int,因为第一个需要比第二个更多的存储,因此信息可能会丢失 . 要强制执行此类转换,我们必须执行显式转换 .
    Type - Conversion

  • 60

    有时候,可以在面试时询问这样的问题 .

    例如,当你写:

    int a = 2;
    long b = 3;
    a = a + b;
    

    没有自动类型转换 . 在C中,编译上面的代码不会有任何错误,但在Java中你会得到像 Incompatible type exception 这样的东西 .

    所以要避免它,你必须编写如下代码:

    int a = 2;
    long b = 3;
    a += b;// No compilation error or any exception due to the auto typecasting
    
  • 0

    主要区别在于 a = a + b ,没有进行类型转换,因此编译器因为没有进行类型转换而生气 . 但是对于 a += b ,它真正做的是将 b 类型转换为与 a 兼容的类型 . 所以,如果你这样做

    int a=5;
    long b=10;
    a+=b;
    System.out.println(a);
    

    你真正在做的是:

    int a=5;
    long b=10;
    a=a+(int)b;
    System.out.println(a);
    
  • 90

    这里微妙点......

    j 是double并且 i 是int时, i+j 存在隐式类型转换 . Java ALWAYS 在它们之间存在操作时将整数转换为double .

    澄清 i+=j 其中 i 是一个整数而 j 是一个双倍可以描述为

    i = <int>(<double>i + j)
    

    见:this description of implicit casting

    在这种情况下,为了清楚起见,您可能希望将 j 类型转换为 (int) .

  • 11

    Java语言规范defines E1 op= E2 to be equivalent to be E1 = (T) ((E1) op (E2)) where T is a type of E1 and E1 is evaluated once .

    这是一个技术答案,但你可能想知道为什么会这样 . 那么,让我们考虑以下计划 .

    public class PlusEquals {
        public static void main(String[] args) {
            byte a = 1;
            byte b = 2;
            a = a + b;
            System.out.println(a);
        }
    }
    

    这个程序打印什么?

    你猜3吗?太糟糕了,这个程序不会编译 . 为什么?好吧,它恰好在Java is defined to return an int中添加了字节 . 我相信这是因为Java虚拟机没有定义保存在字节码上的字节操作(毕竟这些操作数量有限),而使用整数操作则是在语言中公开的实现细节 .

    但是如果 a = a + b 不起作用,那就意味着如果 E1 += E2 被定义为 E1 = E1 + E2a += b 将永远不会对字节起作用 . 如前所述例子显示,情况确实如此 . 作为使 += 运算符用于字节和短路的hack,有一个隐式转换 . 它被删除了's not that great of a hack, but back during the Java 1.0 work, the focus was on getting the language released to begin with. Now, because of backwards compatibility, this hack introduced in Java 1.0 couldn' .

相关问题