问题
I was doing a review of some code and came across an instance of someone post-incrementing a member variable that was a wrapper class around Integer. I tried it myself and was genuinely surprised that it works.
Integer x = 0;
System.out.print(x++ + ", ");
System.out.print(x);
This prints out 0, 1
, not 0, 0
as I would have expected. I've looked through the language specification and can't find anything covering this. Can anyone explain to me why this works and if it's safe across multiple platforms? I would have thought that this would decompose into
Integer x = 0;
int temp1 = x.intValue();
int temp2 = temp1 + 1;
System.out.println(temp1);
temp1 = temp2;
System.out.println(x.intValue());
But apparently there's something in the specification that make it add x = temp1;
before the last line
回答1:
It's perfectly safe to use across platforms. The behavior is specified in §15.4.2 of the Java Language Specification (emphasis added):
The result of the postfix expression must be a variable of a type that is convertible (§5.1.8) to a numeric type, or a compile-time error occurs.
The type of the postfix increment expression is the type of the variable. The result of the postfix increment expression is not a variable, but a value.
At run-time, if evaluation of the operand expression completes abruptly, then the postfix increment expression completes abruptly for the same reason and no incrementation occurs. Otherwise, the value 1 is added to the value of the variable and the sum is stored back into the variable. Before the addition, binary numeric promotion (§5.6.2) is performed on the value 1 and the value of the variable. If necessary, the sum is narrowed by a narrowing primitive conversion (§5.1.3) and/or subjected to boxing conversion (§5.1.7) to the type of the variable before it is stored. The value of the postfix increment expression is the value of the variable before the new value is stored.
EDIT Here's a more accurate equivalent of what's going on in your example code:
Integer x = 0;
int temp = x.intValue();
x = temp + 1; // autoboxing!
System.out.println(temp + ", ");
System.out.println(x.intValue());
回答2:
As of Java 1.5, Java performs auto-unboxing to convert "wrapper types" such as Integer
to the corresponding primitive type int
when necessary. Then the increment operator can work on the resulting int
.
回答3:
It is a "new" feature in Java 5 called autoboxing - Integer is transformed to in when needed - and vice-versa. Same applies to Float, Double, Boolean etc.
While it is a convenient feature, it can lead to a HUGE performance hit if you are not careful
回答4:
Note that the output would be as expected if the increment operation were moved to a method:
public void printIncrement(Integer x1) {
System.out.print(x1++ + ", ");
}
That's because Java passed a copy of the reference so you're now working with a new reference object, x1 instead of x. The original Integer object that x was pointing to stays unchanged and x still points to it.
This can easily bite you when doing calculations in a method if you forget about it.
回答5:
Answer by Sir Tedd Hopp is at a very complex level for programmers who are programming only for few or couple of years.
Let me clear your doubt in simple way suppose
Integer x=10;
x++;
System.out.println(x) ;
output will be 11
Because ++ either post or pre increment is doing Addition by 1 only internally
ie x+1 is what it has to perform and put back the result in the same variable.
ie x=x+1;
now we all know that + operator can only take primitives but x is object , then we have auto-unboxing and auto-boxing concept. so the expression becomes
x.intValue()+1;//step 1 auto-unboxing
x=Integer.valueOf(x.intValue()+1);//step 2 auto-boxing
Hence output comes as 11 after another step of auto-unboxing inside the println statement.
来源:https://stackoverflow.com/questions/13280134/why-does-post-increment-work-on-wrapper-classes