public class class2 {
public static void main(String args[]){
int h=4;
h+=h-=h*h;
System.out.println("-----h:"+h);
}
}
这里为什么在最终结果出来之前h参与中间运算的值始终是4,在做完h-=h*h这个后h的值不会变么?
这个问题在C语言里貌似是属于“未定义行为”,编译器会发出警告.java为什么不报错呢?
public static void main(String args[]){
int h=4;
h+=h-=h*h;
System.out.println("-----h:"+h);
}
}
这里为什么在最终结果出来之前h参与中间运算的值始终是4,在做完h-=h*h这个后h的值不会变么?
这个问题在C语言里貌似是属于“未定义行为”,编译器会发出警告.java为什么不报错呢?
应该是它们为h赋值的时机不太一样吧。
我们可以分开写,避免歧义:
h -= h * h;
h += h;
这样Java算出来也是-24。
因为只有最后的计算出来值才赋值给h,其他的都引用的初始值。
int h=4;
h+=h-=h*h;
等效于:
int h=4;
h+=h-=16;
从左往右计算:
(h+=h)-=16
等效于:
h=8;
h-=16;
最后得到h=-8
即 h = 4 - 16 = -12
现在 h = -123. h = h + h = -12 + -12 = -24
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.7
15.7.1. Evaluate Left-Hand Operand First The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated. If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.
简而言之,二元运算符左面部分必须在右面之前演算。如果是个复合型的赋值预算 +=,-=, *= .....,符号左边的部分(也就变量名那部分)会先将变量当时的值先保存下来,然后再运行右面的表达式,最后再赋值。int h=4;
h+=(h+=1)+(h-=h*h); // 这行5个h,分别叫做h1~h5运算的顺序是:
h1=4,结果4暂时保存x
(h2=4)+1 = 5,写入h,结果5暂时保存y
h3=5,5暂时保存
h4=5, h5=5, 5*5=25
5-25=-20,写入h,结果-20暂时保存z读出刚才保存的y=5和z=-20, y+z = 5 + -20 = -15
读出刚才保存的x=4,4 + -15 = -11
整个表达式及最后的h=-11
h1=4,结果4暂时保存x
(h2=4)+1 = 5,写入h从此之后h的值,也就是h3~h5=5,结果5暂时保存y
h3=5,5暂时保存
h4=5, h5=5, 5*5=25
5-25=-20,写入h,结果-20暂时保存z 读出刚才保存的y=5和z=-20, y+z = 5 + -20 = -15
读出刚才保存的x=4,4 + -15 = -11
整个表达式及最后的h=-11
h+=h-=16;
h+=4-16;
h=h+(4-16);
h=4-12;
h=-8;