在下面的例子:是否有每個循環中創建的新變量?
for(int i=0; i<10; i++) {
int k;
}
這是真的,循環體(即,語句「INT K」)將被重複執行10次?
如果是這樣的話,是否意味着每次都會有創造了一個新的變量k? (因爲這種「類型後跟一個變量名」格式定義爲在JAVA創建一個新的變量雖然變量名保持相同)
在下面的例子:是否有每個循環中創建的新變量?
for(int i=0; i<10; i++) {
int k;
}
這是真的,循環體(即,語句「INT K」)將被重複執行10次?
如果是這樣的話,是否意味着每次都會有創造了一個新的變量k? (因爲這種「類型後跟一個變量名」格式定義爲在JAVA創建一個新的變量雖然變量名保持相同)
否,該變量的存儲器的方法中存在,而不是在循環。您只能在循環內訪問k
的事實僅由編譯器完成。
如果你要改變這樣的代碼:
public class X
{
public static void main(final String[] argv)
{
for(int i = 0; i < 10; i++)
{
int k = i * 2;
System.out.println(k);
}
}
}
然後運行javap的-c X查看字節碼,你會看到:
0: iconst_0
1: istore_1 // i = 0
2: iload_1
3: bipush 10
5: if_icmpge 25 // i < 10
8: iload_1
9: iconst_2
10: imul
11: istore_2 // k = i * 2 < this is the key (see below)
12: getstatic
15: iload_2 // this gets k (see below)
16: invokevirtual #3
19: iinc 1, 1 // i++
22: goto 2
25: return
istore_2
存儲計算的結果爲在堆棧中的第二個點。 iload_2
獲取堆棧中第二個點的值。 (您可以看到指令說明here)
堆棧一直存在,將其視爲一個方法可以訪問某個部分的數組。
確實循環體(也就是語句「int k」)會被重複執行10次嗎?
它你的意思正是依靠。正在使用的有關將啓動堆棧插槽k
,但它被分配在方法入口,而不是循環條目。
如果是這種情況,那麼這是否意味着每次都會創建一個新的變量k? (因爲這種「類型後跟一個變量名」格式定義爲在JAVA創建一個新的變量雖然變量名保持相同)。
變量是由編譯器創建的。它佔用的地址空間在方法輸入時創建,參見上文。
相反在註釋某些權利要求中,這是完全由Java Virtual Machine Specification §2.6指定:
一個新幀的每個被調用的方法時創建。框架在其方法調用完成時被銷燬,無論該框架是正常還是突然(它引發未捕獲的異常)。幀是從創建幀的線程的Java虛擬機堆棧(第2.5.2節)分配的。每個幀具有其自己的局部變量的陣列(§2.6.1),它自己的操作數堆棧(§2.6.2),以及運行時常量池的引用(2.5.5節)的類的當前方法的。
EJP,這是一個關於Java語言的問題。因此,唯一的權威來源是Java語言規範。澄清我的意思:這個問題顯然不能通過查看CIL規範來解決。即使我實現了Java - > CIL編譯器,這個事實也不會改變!從Java到JVM字節碼(或CIL)的翻譯可能會使得一個論點成爲事實,或者是偶然的,而不是通用的。指向JVM規範來解釋Java語言的語義是*反向推理*。 – aioobe
由於聲明int k
只聲明變量(分配一個int塊)並且沒有定義它,所以不會每次都創建一個新變量。
此外,局部變量的範圍應儘可能小。因此,聲明變量的唯一好方法是在while循環中。
如果你想節省時鐘週期,當你初始化一個變量例如int k = 3;
,爲了節省額外的時鐘時間,你可以在while循環之外聲明,從而增加變量的範圍。在這種情況下,變量不會每次都被初始化。
'我提出這個問題只是爲了讓自己明確,一致地表達JAVA語言本身,而不是出於任何實際的原因。正如前面的答案,如果我們檢查字節代碼,我們可以知道沒有新的變量或空間分配,但是這種格式/表達式(我的意思是,在最後9個循環中,「int k」語句實際上什麼都不做)從邏輯上來說,像我這樣的新手會感到困惑。' – istrueright
是的,變量k
創建了10次。
但是這並不意味着任何性能,因爲Java編譯器會知道這10個變量的使用不會重疊。因此,它可能重複使用相同的存儲器(或寄存器)。
所以不要害怕創建很多變量,沒關係。更害怕用new
創建對象。但即使如此,編譯器還是會優化其中的一部分。
不,該變量由編譯器創建一次,並且在輸入方法時創建一次它佔用的幀插槽。 – EJP
沒有變量「創建」。在棧上只有一個int大小的空間是保留的;而且同樣的空間被反覆使用。 –
在這個_特定的例子中,如果你實際編譯並運行它,可能沒有任何'k'變量,因爲編譯器會優化它,因爲它沒有被使用。 –
無論其他人在下面說什麼,Java語言都不會指定如何或何時分配變量。 1)你不能說身體是否被執行了0次,或者10次,因爲它不執行任何操作。 JVM可以自由地忽略所有的循環,如果它喜歡。如果你有例如印刷的東西,那麼是的,它會執行10次。 2)只有*一個*變量'k'。您無需關心何時或如何「創建」。你需要知道的是a)它被綁定到循環體,並且不能被外部訪問,b)在每次迭代中該值將「重置」。 – aioobe