为什么Java的+ =,-=,* =,/ =复合赋值运算符不需要强制转换?

拥有回忆 提交于 2020-02-01 10:33:43

直到今天,我还以为例如:

i += j;

只是以下方面的捷径:

i = i + j;

但是,如果我们尝试这样做:

int i = 5;
long j = 8;

那么i = i + j; 不会编译,但是i += j; 会编译的很好。

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


#1楼

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

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

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


#2楼

有时,可以在面试中提出这样的问题。

例如,当您编写时:

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

#3楼

主要区别在于,使用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);

#4楼

这里的微妙之处...

j为双精度数且i为整数时, i+j有一个隐式类型转换。 当它们之间存在运算时,Java 总是将整数转换为双精度

为了澄清i+=j ,其中i是整数, j是双精度数,可以描述为

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

请参阅: 此隐式转换描述

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


#5楼

Java语言规范E1 op= E2定义为等效于E1 = (T) ((E1) op (E2)) ,其中TE1的类型,并且E1被评估一次

这是一个技术性的答案,但您可能想知道为什么会这样。 好,让我们考虑以下程序。

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

该程序打印什么?

你猜3吗? 太糟糕了,该程序无法编译。 为什么? 好吧,碰巧在Java 中定义了字节加法以返回int 。 我相信这是因为Java虚拟机没有定义要保存在字节码上的字节操作(毕竟,字节码数量有限),而使用整数运算代替的是一种语言公开的实现细节。

但是,如果a = a + b不起作用,则意味着如果将E1 += E2定义为E1 = E1 + E2a += b永远不会对字节起作用。 如前面的示例所示,情况确实如此。 作为使+=运算符适用于字节和短裤的技巧,其中涉及隐式强制转换。 这并不是什么骇人听闻的事,但是在Java 1.0工作期间,重点就在于开始发布该语言。 现在,由于向后兼容,无法删除Java 1.0中引入的这种hack。


#6楼

与这些问题一样,JLS保留了答案。 在这种情况下,第1.5.26.2节“复合赋值运算符” 。 摘录:

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

§15.26.2中引用的示例

[...]以下代码正确:

 short x = 3; x += 4.6; 

并导致x的值为7,因为它等效于:

 short x = 3; x = (short)(x + 4.6); 

换句话说,您的假设是正确的。


#7楼

如果i = i + l则需要从long explicitlyint ,然后它将进行编译并提供正确的输出。 喜欢

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.

但是在+=情况下,它就可以正常工作,因为运算符会隐式执行从右变量类型到左变量类型的类型转换,因此无需显式转换。


#8楼

很好的问题。 Java语言规范证实了您的建议。

例如,以下代码是正确的:

 short x = 3; x += 4.6; 

并导致x的值为7,因为它等效于:

 short x = 3; x = (short)(x + 4.6); 

#9楼

是,

基本上当我们写

i += l; 

编译器将此转换为

i = (int)(i + l);

我只是检查了.class文件代码。

真是一件好事


#10楼

这种转换的一个很好的例子是使用* =或/ =

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'

#11楼

这里的问题涉及类型转换。

当您添加int和long时,

  1. 将int对象强制转换为long,并且将两者都添加,就得到long对象。
  2. 但是长对象不能隐式转换为int。 因此,您必须明确地做到这一点。

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!