Object[] objs = new Object[5];
for (int i = 0; i < 5; ++i) {
int j = i + 1;
Object obj = objs[i];
}
对于上述循环,我有两个问题:
- 是为每个循环迭代创建
j
变量和obj
引用,还是创建一次然后只重新分配值? ++i
放置而不是i++
作为单个指令来增加值是否有任何性能优势?
是为每个循环迭代创建 j 变量和 obj 引用,还是创建一次然后只重新分配值?
每次都声明和创建
将 ++i 而不是 i++ 作为单个指令来增加值是否有任何性能优势?
并不真地。
是为每个循环迭代创建 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];
//}
我已经比较了代码部分的两个字节码。我没有发现什么特别的。唯一不同的是,在第一个示例代码部分中定义了 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
是为每个循环迭代创建 j 变量和 obj 引用,还是创建一次然后只重新分配值?
理论上是的。在实践中优化代码这不会发生。但是,在您的情况下,可能不会优化 5 个(或少于 10,000 个)的循环,因为它的性能可能并不重要。
将 ++i 而不是 i++ 作为单个指令来增加值是否有任何性能优势?
对于优化的代码,它们在这里是相同的。对于未优化的代码,差异不太重要。
对,他们是!
像这样做 :
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];
}
是的,他们每次都创建,前缀或后缀 ++ 并不重要。
我会尽力回答你的问题......
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
,这无关紧要。