在for循环中使用string.length()值之前将它存储在变量中是否可以在Java中进行任何性能改进?

时间:2014-12-16 03:05:29

标签: java jvm

简而言之,JVM是否在内部优化了以下代码

public void test(String str)
{
    int a = 0;

    for( int i = 0; i < 10; i++)
    {
        a = a + str.length();
    }
}

表现得与以下效率一样高效:

public void test(String str)
{
    int len = str.length();
    int a = 0;

    for( int i = 0; i < 10; i++)
    {
        a = a + len;
    }
}

如果它确实优化了,它是通过内部缓存str.length()值来实现的吗?

2 个答案:

答案 0 :(得分:6)

我创建了以下两种方法,

public void test(String str) {
    int len = str.length();
    int a = 0;
    for (int i = 0; i < 10; i++) {
        a = a + len;
    }
}

public void test2(String str) {
    int a = 0;
    for (int i = 0; i < 10; i++) {
        a = a + str.length();
    }
}

然后我使用javap -v生成第一个方法test

  public void test(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=2
         0: aload_1
         1: invokevirtual #16                 // Method java/lang/String.length:()I
         4: istore_2
         5: iconst_0
         6: istore_3
         7: iconst_0
         8: istore        4
        10: goto          20
        13: iload_3
        14: iload_2
        15: iadd
        16: istore_3
        17: iinc          4, 1
        20: iload         4
        22: bipush        10
        24: if_icmplt     13
        27: return

test2

  public void test2(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=2
         0: iconst_0
         1: istore_2
         2: iconst_0
         3: istore_3
         4: goto          17
         7: iload_2
         8: aload_1
         9: invokevirtual #16                 // Method java/lang/String.length:()I
        12: iadd
        13: istore_2
        14: iinc          3, 1
        17: iload_3
        18: bipush        10
        20: if_icmplt     7
        23: return

所以答案似乎是存储长度一次有一些优势(它产生更短的字节码,相当于23对27行),这似乎暗示可能表现更好,但我怀疑它实际上可以衡量。特别是在代码被JIT编译之后)。

最后,您可以考虑

public void test(String str)
{
  int a = 0;
  for( int i = 0, len = str.length(); i < 10; i++) {
    a = a + len;
  }
}

或只是

int a = 10 * str.length();

答案 1 :(得分:6)

好的回答Elliot F.

我做了一个更简单的测试,并且运行了两个方法,重复次数非常多,并且每个方法都有时间。

第一种方法(其中长度仅计算一次)始终比第二种方法快。

这是我创建的整个测试课程;

package _testing;

import java.util.Date;

public class Speed {

    long count = 5000000;
    public static void main(String[] args) {

        long start, finish; 
        Speed sp = new Speed(); 

        start = new Date().getTime();
        sp.test("test");
        finish = new Date().getTime();
        System.out.println("test 1:"+(finish - start));

        start = new Date().getTime();
        sp.test2("test");
        finish = new Date().getTime();
        System.out.println("test 2:"+(finish - start));

    }


    public void test(String str) {
        int len = str.length();
        int a = 0;
        for (int i = 0; i < count; i++) {
            a = a + len;
        }
    }

    public void test2(String str) {
        int a = 0;
        for (int i = 0; i < count; i++) {
            a = a + str.length();
        }
    }   
}

输出看起来像这样;

test 1:7
test 2:22