第二個是我更喜歡的。除了範圍界定之外,沒有功能上的差異。
在每次迭代中設置相同的變量沒有區別,因爲Integer
是不可變的類。現在,如果你是修改一個對象,而不是每次創建一個新對象,那麼就會有所不同。
作爲一個附註,在這個代碼中,您應該使用int
和Integer.parseInt()
而不是Integer
和Integer.parse()
。你引入了很多不必要的裝箱和拆箱。
編輯:這已經有一段時間,因爲我在字節碼打亂身邊,所以我想我會再次讓我的手髒。
下面是測試類我編譯:
class ScopeTest {
public void outside(String[] args) {
Integer total = 0;
Integer i;
for (String str : args)
{
i = Integer.valueOf(str);
total += i;
}
}
public void inside(String[] args) {
Integer total = 0;
for (String str : args)
{
Integer i = Integer.valueOf(str);
total += i;
}
}
}
字節碼輸出(編譯後javap -c ScopeTest
檢索):
Compiled from "ScopeTest.java"
class ScopeTest extends java.lang.Object{
ScopeTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public void outside(java.lang.String[]);
Code:
0: iconst_0
1: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_2
5: aload_1
6: astore 4
8: aload 4
10: arraylength
11: istore 5
13: iconst_0
14: istore 6
16: iload 6
18: iload 5
20: if_icmpge 55
23: aload 4
25: iload 6
27: aaload
28: astore 7
30: aload 7
32: invokestatic #3; //Method java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
35: astore_3
36: aload_2
37: invokevirtual #4; //Method java/lang/Integer.intValue:()I
40: aload_3
41: invokevirtual #4; //Method java/lang/Integer.intValue:()I
44: iadd
45: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
48: astore_2
49: iinc 6, 1
52: goto 16
55: return
public void inside(java.lang.String[]);
Code:
0: iconst_0
1: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_2
5: aload_1
6: astore_3
7: aload_3
8: arraylength
9: istore 4
11: iconst_0
12: istore 5
14: iload 5
16: iload 4
18: if_icmpge 54
21: aload_3
22: iload 5
24: aaload
25: astore 6
27: aload 6
29: invokestatic #3; //Method java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
32: astore 7
34: aload_2
35: invokevirtual #4; //Method java/lang/Integer.intValue:()I
38: aload 7
40: invokevirtual #4; //Method java/lang/Integer.intValue:()I
43: iadd
44: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
47: astore_2
48: iinc 5, 1
51: goto 14
54: return
}
出乎我的意料,有兩個之間的一個區別:outside()
,變量i
仍然佔用了一個寄存器,即使它從實際代碼中被省略(請注意,所有的iload
和istore
指令都指向一個更高的寄存器)。
JIT編譯器應該縮短這種差異的工作量,但您仍然可以看到限制範圍是一種很好的做法。 (關於我前面的注意事項,你可以看到要添加兩個Integer對象,Java必須用intValue
取代兩個整數對象,然後添加它們,然後用valueOf
創建一個新的Integer,不要這樣做,除非絕對因爲這是沒有意義的和較慢。)
我假設你的實際循環比你的示例更復雜,實際上使得我不僅僅是一個臨時變量或其他東西... – BoltClock 2010-05-21 21:18:12
爲什麼你首先使用昂貴的Integer而不是int? – bmargulies 2010-05-21 21:23:50
我建議你重新提出問題的方式,重點放在你想要發現的問題上。在Integer中裝箱,取消裝箱和「新」的例子中,效率非常低,它遠遠超過了關於變量範圍的任何理論微觀優化。 – Yishai 2010-05-21 21:35:41