简体   繁体   English

“+=”运算符在 Java 中有什么作用?

[英]What does the "+=" operator do in Java?

您能帮我理解以下代码的含义吗:

x += 0.1;

The "common knowledge" of programming is that x += y is an equivalent shorthand notation of x = x + y .编程的“常识”是x += yx = x + y的等效简写符号。 As long as x and y are of the same type (for example, both are int s), you may consider the two statements equivalent.只要xy的类型相同(例如,两者都是int s),您就可以认为这两个语句是等价的。

However, in Java, x += y is not identical to x = x + y in general.但是,在 Java 中, x += y通常x = x + y

If x and y are of different types, the behavior of the two statements differs due to the rules of the language.如果xy的类型不同,则这两个语句的行为因语言规则而异。 For example, let's have x == 0 (int) and y == 1.1 (double):例如,让我们有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'

+= performs an implicit cast, whereas for + you need to explicitly cast the second operand, otherwise you'd get a compiler error. +=执行隐式转换,而对于+您需要显式转换第二个操作数,否则会出现编译器错误。

Quote from Joshua Bloch's Java Puzzlers :引自 Joshua Bloch 的Java Puzzlers

(...) compound assignment expressions automatically cast the result of the computation they perform to the type of the variable on their left-hand side. (...) 复合赋值表达式会自动将它们执行的计算结果转换为左侧变量的类型。 If the type of the result is identical to the type of the variable, the cast has no effect.如果结果的类型与变量的类型相同,则强制转换无效。 If, however, the type of the result is wider than that of the variable, the compound assignment operator performs a silent narrowing primitive conversion [ JLS 5.1.3 ].然而,如果结果的类型比变量的类型更宽,复合赋值运算符将执行静默缩小原语转换 [ JLS 5.1.3 ]。

  • x += y is x = x + y x += yx = x + y
  • x -= y is x = x - y x -= yx = x - y
  • x *= y is x = x * y x *= yx = x * y
  • x /= y is x = x / y x /= yx = x / y
  • x %= y is x = x % y x %= yx = x % y
  • x ^= y is x = x ^ y x ^= yx = x ^ y
  • x &= y is x = x & y x &= yx = x & y
  • x |= y is x = x | y x |= yx = x | y x = x | y

and so on ...等等 ...

It's one of the assignment operators .它是赋值运算符之一 It takes the value of x , adds 0.1 to it, and then stores the result of (x + 0.1) back into x .它取x的值,加上 0.1,然后将 (x + 0.1) 的结果存储回x

So:所以:

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

It's functionally identical to, but shorter than:它在功能上与以下内容相同,但比以下内容短:

double x = 1.3;
x = x + 0.1;

NOTE: When doing floating-point math, things don't always work the way you think they will .注意:在进行浮点数学运算时,事情并不总是像您认为的那样工作

devtop += Math.pow(x[i] - mean, 2); will add the result of the operation Math.pow(x[i] - mean, 2) to the devtop variable.Math.pow(x[i] - mean, 2)运算的结果添加到devtop变量中。

A more simple example:一个更简单的例子:

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

In java the default type of numbers like 2 or -2(without a fractional component) is int and unlike c# that's not an object and we can't do sth like 2.tostring as in c# and the default type of numbers like 2.5(with a fractional component) is double;在 java 中,像 2 或 -2(没有小数部分)这样的数字的默认类型是 int,与 c# 不同,它不是一个对象,我们不能像在 c# 中那样做 2.tostring 之类的事情,以及像 2.5(带有小数部分)是双倍的; So if you write:所以如果你写:

short s = 2;
s = s + 4;

you will get a compilation error that int cannot be cast into short also if you do sth like below:如果您执行以下操作,您将收到一个编译错误,即 int 也无法转换为 short:

float f = 4.6;
f = f + 4.3;

you will get two compilation errors for setting double '4.6' to a float variable at both lines and the error of first line is logical because float and double use different system of storing numbers and using one instead of another can cause data loss;在两行将 double '4.6' 设置为 float 变量时,您会遇到两个编译错误,第一行的错误是合乎逻辑的,因为 float 和 double 使用不同的存储数字系统,使用一个而不是另一个会导致数据丢失; two examples mentioned can be changed like this:提到的两个示例可以这样更改:

s += 4
f += 4.3

which both have an implicit cast behind code and have no compile errors;它们都在代码背后隐式转换并且没有编译错误; Another point worthy of consideration is numbers in the range of 'byte' data type are cached in java and thus numbers -128 to 127 are of type byte in java and so this code doesn't have any compile errors:值得考虑的另一点是“字节”数据类型范围内的数字在 java 中缓存,因此数字 -128 到 127 在 java 中属于字节类型,因此此代码没有任何编译错误:

byte b = 127

but this one has an error indeed:但这确实有一个错误:

byte b = 128

because 128 is an int in java;因为 128 是 java 中的 int; about long numbers we are recommended to use an L after the number for the matter of integer overflow like this:关于长数字,我们建议在数字后使用 L 来解决整数溢出问题,如下所示:

long l = 2134324235234235L

in java we don't have operator overloading like c++ but += is overloaded only for String and not for the let's say StringBuilder or StringBuffer and we can use it instead of String 'concat' method but as we know String is immutable and that will make another object and will not change the same object as before :在 java 中,我们没有像 c++ 那样的运算符重载,但是 += 仅针对 String 而不是针对 StringBuilder 或 StringBuffer 重载,我们可以使用它代替 String 'concat' 方法,但是我们知道 String 是不可变的,这将创建另一个对象并且不会像以前一样更改相同的对象:

String str = "Hello";
str += "World";

It's fine;没关系;

devtop += Math.pow(x[i] - mean, 2); adds Math.pow(x[i] - mean, 2) to devtop .添加Math.pow(x[i] - mean, 2)devtop

It increases the value of the variable by the the value after += .它通过+=之后的值增加变量的值。 For example:例如:

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

It's just a shorter version of:它只是一个较短的版本:

x = x+0.1;

You can take a look at the bytecode whenever you want to understand how java operators work.每当您想了解 Java 运算符的工作原理时,都可以查看字节码。 Here if you compile:在这里编译:

int x = 0;
x += 0.1;

the bytecode will be accessible with jdk command javap -c [*.class] :(you can refer to Java bytecode instruction listings for more explanation about bytecode)字节码将可以通过 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)

Now it is clear that java compiler promotes x to double and then adds it with 0.1 .现在很明显,java 编译器将x提升为双倍,然后将其添加0.1
Finally it casts the answer to integer .最后它将答案转换为integer
There is one interesting fact I found out that when you write:当你写作时,我发现了一个有趣的事实:

byte b = 10;
b += 0.1;

compiler casts b to double, adds it with 0.1 , casts the result which is double to integer , and finally casts it to byte and that is because there is no instruction to cast double to byte directly.编译器将b转换为 double ,将其加上0.1 ,将double的结果转换为integer ,最后将其转换为byte ,这是因为没有直接将doublebyte指令。
You can check the bytecode if you doubt :)如果您有疑问,可以检查字节码:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM