4
Object[] objs = new Object[5];
for (int i = 0; i < 5; ++i) {
    int j = i + 1;
    Object obj = objs[i];
}

对于上述循环,我有两个问题:

  1. 是为每个循环迭代创建j变量和obj引用,还是创建一次然后只重新分配值?
  2. ++i放置而不是i++作为单个指令来增加值是否有任何性能优势?
4

7 回答 7

7

是为每个循环迭代创建 j 变量和 obj 引用,还是创建一次然后只重新分配值?

每次都声明和创建

将 ++i 而不是 i++ 作为单个指令来增加值是否有任何性能优势?

并不真地。

于 2012-08-07T11:51:02.113 回答
6

是为每个循环迭代创建 j 变量和 obj 引用,还是创建一次然后只重新分配值?

每次循环时,都会创建一个新的 int 但 obj 只是对现有对象的引用,因此不会触发对象创建。无论如何,JVM 很可能会为您优化它。

将 ++i 而不是 i++ 作为单个指令来增加值是否有任何性能优势?

很可能没有什么值得注意的,而且JVM可能会再次更改您的代码。

底线:使用更具可读性的任何内容,并将变量的范围限制在使用它们的位置。

实际上,JVM 可能会将您的代码更改为此,因为您不在循环中使用局部变量:

Object[] objs = new Object[5];
//for (int i = 0; i < 5; ++i) {
//    int j = i + 1;
//    Object obj = objs[i];
//}
于 2012-08-07T11:52:29.637 回答
3

我已经比较了代码部分的两个字节码。我没有发现什么特别的。唯一不同的是,在第一个示例代码部分中定义了 4 个局部变量,但在第二个示例代码部分中定义了 5 个局部变量。然而,类似的操作码被执行。由于局部变量名称不同,因此执行不同的操作码。我的意思是在第一个示例中'i 被定义为 local-variable-2',在第二个示例中'i 被定义为 local-variable-4'。

但是通过 JVM 工具监控代码执行可以提供额外的信息。由于 Java 是一个平台,而 JVM 可能会优化代码执行,我们可能无法通过查看 java 源代码或 java 字节码来确定。

    Object[] objs = new Object[5];  
    for (int i = 0; i < 5; ++i) {  
       int j = i + 1;  
       Object  obj = objs[i];  
    }  

 local-variable-0=this
 local-variable-1=objs
 local-variable-2=i
 local-variable-3=j

  stack=2, locals=5, args_size=1 
 0: aload_0 
 1: invokespecial #8                  // Method java/lang/Object."<init>":()V 
 4: iconst_5 
 5: anewarray     #3                  // class java/lang/Object 
 8: astore_1 #store created object referance to local value-1 (objs)
 9: iconst_0 #push 0 on stack
10: istore_2  # local-value-2(i) assigned 0
11: goto          26 
14: iload_2  #load localvalue 2(i)
15: iconst_1 # ++i operation
16: iadd  #i+1
17: istore_3 #assign i+1 into local-variable-3(j)
18: aload_1 # push object in local varable 1 (objs) onto the stack
19: iload_2 # push integer in local variable 2 (i) onto the stack
20: aaload  # retrieve entry
21: astore        4 # push value on stack into local-variable-4 (obj)
23: iinc          2, 1 # local-variable-2(i)++
26: iload_2 
27: iconst_5 
28: if_icmplt     14 for(if i==5)
31: return 

 **************************************************************************
  Object[] objs = new Object[5];  
    int j; 
    Object obj; 
    for (int i = 0; i < 5; ++i) {  
        j = i + 1;  
        obj = objs[i];  
    }  

  local-variable-0=this
 local-variable-1=objs
 local-variable-2=j
 local-variable-3=obj
 local-variable-4=i

  stack=2, locals=5, args_size=1 
     0: aload_0 
     1: invokespecial #8                  // Method java/lang/Object."<init>":()V 
     4: iconst_5 
     5: anewarray     #3                  // class java/lang/Object 
     8: astore_1 #store created object referance to local value-1 (objs)
     9: iconst_0 #push zero on to the stack
    10: istore        4 # local variable-4(i) is assigned zero
    12: goto          28 
    15: iload         4 
    17: iconst_1 
    18: iadd  #i+1
    19: istore_2  #j is set 
    20: aload_1  #load objs
    21: iload         4 #load i
    23: aaload 
    24: astore_3  #obj=objs[i]
    25: iinc          4, 1 # i++
    28: iload         4 
    30: iconst_5 
    31: if_icmplt     15 # if i==5
    34: return 
于 2012-08-07T12:04:39.727 回答
1

是为每个循环迭代创建 j 变量和 obj 引用,还是创建一次然后只重新分配值?

理论上是的。在实践中优化代码这不会发生。但是,在您的情况下,可能不会优化 5 个(或少于 10,000 个)的循环,因为它的性能可能并不重要。

将 ++i 而不是 i++ 作为单个指令来增加值是否有任何性能优势?

对于优化的代码,它们在这里是相同的。对于未优化的代码,差异不太重要。

于 2012-08-07T12:00:51.823 回答
1

对,他们是!

像这样做 :

Object[] objs = new Object[5]; 
int j = 0;
Object obj = new Object();
for (int i = 0; i < 5; ++i) {   
   j = i + 1;   
   obj = objs[i]; 
} 
于 2012-08-07T11:52:38.977 回答
1

是的,他们每次都创建,前缀或后缀 ++ 并不重要。

于 2012-08-07T11:54:58.643 回答
1

我会尽力回答你的问题......

Are the j variable and obj reference created for every loop iteration or they are created once and then only reassigned the values?

int j每次都创建,并且每次在循环内Object Reference Variable obj也创建,但不是OBJECT

Is there any perfomance benefit of putting ++i instead of i++ as a single instruction to increment the value?

在这种情况下,没有分配 j's value这无关紧要。

于 2012-08-07T12:55:54.240 回答