5
public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

根据Android 文档,在上面的代码中,零速度较慢。但我不明白为什么?好吧,我还没有学得那么深,但据我所知,这length是一个领域而不是方法。那么当循环检索它的值时,它与从局部变量中检索有什么不同呢?一旦初始化,数组长度总是固定的。我错过了什么?

4

4 回答 4

8

好吧,我想这是因为在zero,他总是需要从mArray和检索信息one,他可以访问它。这意味着,zero需要两个“方法”:

  1. 访问 mArray
  2. 访问 mArray.length

one只需要一种“方法”:

  1. 访问镜头
于 2013-08-13T10:08:39.780 回答
3

在第一个示例中,JVM 需要首先获取对数组的引用,然后访问其长度字段。

在第二个例子中,它只访问一个局部变量。

在桌面 JVM 上,这通常是优化的,这两种方法是等效的,但似乎 Android 的 JVM 并没有这样做......但是......

于 2013-08-13T10:09:52.317 回答
2

这是范围的问题。访问实例变量比访问方法变量慢,因为它没有存储在相同的内存位置。(因为方法变量可能被更频繁地访问)。

len 也是如此,但有一个额外的优化。len无法从方法外部更改,编译器可以看到它永远不会更改。因此,其值更具可预测性,并且可以进一步优化循环。

于 2013-08-13T10:13:16.857 回答
2
  public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

在这里,如果您查看每次迭代都会计算 for 循环数组长度,这会降低性能。

  public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

在这种情况下,长度在 for 循环之前计算,然后在循环中使用。

于 2013-08-13T10:09:40.603 回答