Java中的"+="运算符是什么意思?

57

你能帮我理解下面这段代码的意思吗:

x += 0.1;

2
看起来是将0.1加到一个名为x的变量中。 - Friek
1
几乎是 https://dev59.com/IHRB5IYBdhLWcg3weXSX 的副本。 - rds
8个回答

143
"常见的编程知识"是,x += yx = x + y 的等价简写。只要 xy 是相同类型(例如都是 int),你可以认为这两个语句是等价的。
然而,在 Java 中,x += y 通常不等同于 x = x + y
如果 xy 是不同类型的,则由于语言规则,两个语句的行为会有所不同。例如,假设 x == 0(int)和 y == 1.1(double): "
    int x = 0;
    x += 1.1;    // just fine; hidden cast, x == 1 after assignment
    x = x + 1.1; // won't compile! 'cannot convert from double to int'

+=执行隐式转换,而对于+,您需要显式转换第二个操作数,否则会出现编译器错误。

引用自Joshua Bloch的Java Puzzlers

(...) 复合赋值表达式自动将它们执行计算的结果强制转换为左侧变量的类型。如果结果的类型与变量的类型相同,则转换没有任何效果。然而,如果结果的类型比变量的类型更宽,则复合赋值运算符执行静默缩小原始转换 [JLS 5.1.3]。


2
此外,如果 x 是一个更复杂的表达式(比如数组或字段访问),而不是单个变量,它的组成表达式现在只会被计算一次,而不是两次。 - Paŭlo Ebermann
X – = Y + 1 的意思是 X- =(Y+1),也就是 X= X-(Y+1)=X-Y-1,对吗?但是有些地方给出的是 X – = Y + 1 的意思是 X= X- Y+1,那么哪一个是正确的呢?@jakub.g - Mithlesh Upadhyay
@MithleshUpadhyay 第一句话是什么意思?你第二个想法从哪里得来的? - wizzwizz4
这个答案有点难以理解。它强调x += y不等同于x = x + y,但实际上它们大多数情况下是相同的。只有在一些罕见的用例中它们才不同(即使在这种情况下,它们也大多相同)。 - anatolyg
@anatolyg,你是对的。最初我写这个答案的时候是很久以前,在许多“它与x = x + y完全相同”的答案中。我重新措辞了答案,使其更易于理解。 - jakub.g

29
  • x += y翻译为x = x + y
  • x -= y翻译为x = x - y
  • x *= y翻译为x = x * y
  • x /= y翻译为x = x / y
  • x %= y翻译为x = x % y
  • x ^= y翻译为x = x ^ y
  • x &= y翻译为x = x & y
  • x |= y翻译为x = x | y

等等...


+= 是怎么样的?它可以编译但是没有任何效果。 - kommradHomer
1
@kommradHomer x =+ y 相当于 x = y - Eng.Fouad
4
x =+ y等同于x = 0 + y。请注意,这里的操作符是+=,而不是=+ - Jacques Marais

13

这是赋值运算符之一。它将x的值加上0.1,然后将(x + 0.1)的结果存回到x中。

因此:

double x = 1.3;
x += 0.1;    // sets 'x' to 1.4

它在功能上与以下代码相同,但更短:

double x = 1.3;
x = x + 0.1;

注意: 在进行浮点数计算时,事情并不总是按照你想象的那样运行 (链接)


3

devtop += Math.pow(x[i] - mean, 2);将结果添加到devtop变量,结果来自于操作Math.pow(x[i] - mean, 2)

一个更简单的例子:

int devtop = 2;
devtop += 3; // devtop now equals 5

2

在Java中,像2或-2(没有小数部分)这样的数字的默认类型是int,与C#不同,它不是一个对象,我们不能像在C#中那样执行2.tostring之类的操作。而像2.5(有小数部分)这样的数字的默认类型是double;

因此,如果您编写:

short s = 2;
s = s + 4;

如果您执行以下操作,将会得到一个编译错误:int 无法转换为 short。

float f = 4.6;
f = f + 4.3;

当你将双精度数'4.6'赋值给float变量时,在两行代码中你会得到两个编译错误。第一行的错误是合乎逻辑的,因为float和double使用不同的数字存储系统,使用其中一个可能会导致数据丢失。可以通过以下方式更改上述两个示例:

s += 4
f += 4.3

这段代码中既有隐式类型转换,又没有编译错误; 另一个值得考虑的点是,在Java中,“byte”数据类型范围内的数字被缓存,因此-128到127之间的数字在Java中属于“byte”类型,所以这段代码没有任何编译错误:

byte b = 127

但这个确实有一个错误:

byte b = 128

因为在Java中,128是一个int类型的数;关于长整型数字,我们推荐在数字后面加上L,以防止整数溢出问题,如下所示:

long l = 2134324235234235L

在Java中,我们没有像C++那样的运算符重载,但是+=仅针对String进行了重载,而不是例如StringBuilder或StringBuffer。我们可以使用它来代替String的'concat'方法,但是正如我们所知道的,String是不可变的,这将创建另一个对象,而不会更改之前的同一对象:
String str = "Hello";
str += "World";

没问题。


2

如果你想要了解Java运算符的工作原理,可以随时查看字节码。在这里,如果你进行编译:

int x = 0;
x += 0.1;

字节码可以通过 JDK 命令 javap -c [*.class] 来访问:(您可以参考 Java 字节码指令列表 以了解有关字节码的更多解释)

0: iconst_0 //  load the int value 0 onto the stack
1: istore_1 //  store int value into variable 1 (x)
2: iload_1 // load an int value from local variable 1 (x)
3: i2d // convert an int into a double (cast x to double)
4: ldc2_w        #2                  // double 0.1d -> push a constant value (0.1) from a constant pool onto the stack
7: dadd //  add two doubles (pops two doubles from stack, adds them, and pushes the answer onto stack)
8: d2i // convert a double to an int (pops a value from stack, casts it to int and pushes it onto stack)
9: istore_1 // store int value into variable 1 (x)

现在很清楚,Java编译器将 x 提升为 double 类型,然后将其与 0.1 相加。
最后将答案强制转换为 integer 类型。
我发现一个有趣的事实,当你写下以下代码时:
byte b = 10;
b += 0.1;

编译器将b转换为双精度浮点数,与0.1相加,然后将结果转换为整数,最后将其转换为字节。这是因为没有直接将double转换为byte的指令。
如果怀疑的话,可以检查字节码 :)

1

devtop += Math.pow(x[i] - mean, 2);Math.pow(x[i] - mean, 2)加到devtop中。


0

它通过+=后面的值增加变量的值。 例如:

float x = 0;
x += 0.1;
//x is now 0.1
x += 0.1;
//x is now 0.2

这只是一个更短的版本:

x = x+0.1;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接