这是
javac从JDK 9开始的错误(该错误在字符串连接方面进行了一些更改,我怀疑这是问题的一部分),已由
javac团队确认为错误IDJDK-8204322。如果查看该行的相应字节码:
array[i++%size] += i + " ";
它是:
21: aload_2 22: iload_3 23: iinc 3, 1 26: iload_1 27: irem 28: aload_2 29: iload_3 30: iinc 3, 1 33: iload_1 34: irem 35: aaload 36: iload_3 37: invokedynamic #5, 0 // makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String; 42: aastore
最后一个
aaload是数组的实际负载。但是,部分
21: aload_2 // load the array reference 22: iload_3 // load 'i' 23: iinc 3, 1 // increment 'i' (doesn't affect the loaded value) 26: iload_1 // load 'size' 27: irem // compute the remainder
其中大约
array[i++%size]两次对应于表达式(减去实际的加载和存储)。正如规范在jls-15.26.2中所说,这是不正确的:
形式的复合赋值表达式
E1 op= E2等效于E1 = (T) ((E1) op (E2)),其中T是的类型E1, 不同之
处在于该表达式 仅被评估一次。E1
因此,对于表达式
array[i++%size] += i + "";,该零件
array[i++%size]仅应评估一次。但是它会被评估两次(一次加载,一次存储)。
是的,这是一个错误。
一些更新:
该错误已在JDK 11中修复,并且将有一个JDK
10的反向端口(但JDK
9
没有,因为它不再接收公共更新)。
Aleksey
Shipilev在JBS页面上(以及此处的@DidierL)中提到:
解决方法:编译
-XDstringConcat=inline
这将恢复为
StringBuilder用于进行串联的操作,并且没有错误。


![为什么array [idx ++] + =“ a”在Java 8中增加一次idx,在Java 9和10中增加两次? 为什么array [idx ++] + =“ a”在Java 8中增加一次idx,在Java 9和10中增加两次?](http://www.mshxw.com/aiimages/31/430920.png)
