首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java如何决定数学表达式中的哪个运算符必须装箱?

Java如何决定数学表达式中的哪个运算符必须装箱?
EN

Stack Overflow用户
提问于 2015-06-01 12:51:02
回答 2查看 101关注 0票数 5

我目前正在写关于如何编写有效Java代码的学士论文。以下四个代码片段是JMH基准测试的一部分,它将执行每个方法100万次。

代码语言:javascript
复制
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;
}

这四种方法的结果如下:

  • primitiveOnly: 1.7ms/操作
  • primitiveToWrapper: 2.2ms/操作
  • wrapperToPrimitive: 47.5ms/操作
  • wrapperToWrapper: 48.2ms/操作

这种行为的原因是,在primitiveToWrapper中的操作期间,Integer值必须被取消装箱,在wrapperToPrimitive中的操作中,必须将第一个操作数框到整数中,这会导致创建一个昂贵的对象。

Java是否有这样的行为的具体原因?我读了一遍Java语言规范,但没能找到这个问题的答案。

更新:

为了解决返回值的问题(感谢Phil ),我更新了我的代码。此外,我将基准测试类中的所有Integer变量更改为int。这是新版本:

代码语言:javascript
复制
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万次执行)。

  • primitiveOnly: 0.783
  • primitiveToWrapper (int假人):0.735
  • primitiveToWrapper (整数虚拟人):24.999
  • WrapperToPrimitive (int假人):0.709
  • WrapperToPrimitive (整数虚拟人):26.782
  • WrapperToWrapper (int假人):0.764
  • WrapperToWrapper (整数虚拟人):27.301

最终的结果现在感觉更加直观了。谢谢大家的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-01 13:00:10

在第二段代码中,每次将值赋值给虚拟java时,都必须将其放入Integer中,因为这是varaible的类型。它不知道您从来没有在上面调用过任何方法,而且它可能是一个简单的int。

因此,每次它命中代码dummy += (add1 + add2);时,都必须执行以下操作。

  • 开箱假人
  • 执行加法
  • 将结果放回虚拟框中

它每次都会通过for循环执行此操作。

票数 3
EN

Stack Overflow用户

发布于 2015-06-01 13:31:01

这是因为当dummy是整数时,它的值是不可变的。参见例如为什么整数在Java中是不可变的?

基本上,在编写dummy += (add1 + add2);的最后一个方法中,它意味着

代码语言:javascript
复制
dummy = Integer.valueOf(dummy.intValue() + add1.intValue() + add2.intValue());

每次在循环中,都需要分配一个新的对象来保持一个新的整数值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30573975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档