我目前正在撰写有关如何编写有效Java代码的学士论文。以下四个代码段是JMH基准测试的一部分,每个方法将执行每个方法100万次。
public final static int primitiveOnly(int dummy, int add1, int add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static int primitiveToWrapper(int dummy, int add1, Integer add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static int wrapperToPrimitive(Integer dummy, Integer add1, int add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static Integer wrapperToWrapper(Integer dummy, Integer add1, Integer add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
这四种方法的结果是:
这种行为的原因是在primitiveToWrapper的操作期间,Integer值只需要取消装箱,其中wrapperToPrimitive中的操作必须将第一个操作数装入Integer,这会导致昂贵的对象创建。
Java有这样的特定原因吗?我通读了Java Language Specification,但无法找到这个问题的答案。
更新
为了解决关于返回值的问题(感谢Phil Anderson),我更新了我的代码。另外,我将基准类中的所有Integer变量更改为int。这是新版本:
public final static int primitiveOnly(int dummy, int add1, int add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static int primitiveToWrapperIntDummy(int dummy, int add1, Integer add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static Integer primitiveToWrapperIntegerDummy(Integer dummy, int add1, Integer add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static int wrapperToPrimitiveIntDummy(int dummy, Integer add1, int add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static Integer wrapperToPrimitiveIntegerDummy(Integer dummy, Integer add1, int add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static int wrapperToWrapperIntDummy(int dummy, Integer add1, Integer add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
public final static Integer wrapperToWrapperIntegerDummy(Integer dummy, Integer add1, Integer add2) {
for(int i = 0; i < 10; i++) {
dummy += (add1 + add2);
}
return dummy;
}
结果平均为10次迭代(1次迭代=上述每种方法的100次执行)。
最终结果现在感觉更加直观。谢谢大家帮助我。
答案 0 :(得分:3)
在代码的第二位,每次为虚拟java分配一个值都必须将它装入一个Integer,因为这是变量的类型。它不知道你从来没有真正调用任何方法,它可能是一个简单的int。
因此每次遇到代码dummy += (add1 + add2);
时,都必须执行以下操作。
每次通过for循环都会这样做。
答案 1 :(得分:2)
这是因为当dummy
是一个整数时,它的值是不可变的。参见例如Why are Integers immutable in Java?
基本上,在写dummy += (add1 + add2);
的最后一种方法中,它意味着
dummy = Integer.valueOf(dummy.intValue() + add1.intValue() + add2.intValue());
每次循环时,都需要分配一个新对象来保留一个新的整数值。