2013-11-25 76 views
15

我知道,聲明終止符符號;(如果單獨使用)表示空聲明。此外,「空循環體」可以是一個有用的編程結構,並使用空語句進行編寫。之間的任何細微差別;或{}來表示空語句?

看下面的while語句,在第2行上,我決定用一對背靠背的{}大括號替換終止的;符號。代碼編譯並運行正常。這是否意味着Java編譯器將替換空的代碼塊(由「空」{}大括號表示)替換爲;的空語句?

如果Java做了稍微不同的事情,那麼在這兩種情況下,生成的字節碼是否相同? (對不起,我無法檢查這臺ATM機,我是Java的新手,我還沒有顯示和檢查字節碼的必要知識)。

int i=0,j=100; 

// Either a terminating ; symbol or {} braces work to make an "empty loop body". 
while (++i < --j) {} 
System.out.println("The midpoint between 0 and 100 is " +i); // Midpoint is 50. 
+0

實際上我用的'{;}'看到塊,而且要知道,我真的打算把任何在該塊,並沒有只需要創建一個大括號後面的填充。儘管這是我自己的事情,並且從來沒有見過其他人這樣做。 – Cruncher

回答

18

這兩者在語義上是相同的,編譯器將在兩種情況下生成相同的代碼。如果你試圖故意包含一個空的循環體,{}更清楚地表明它是有意的,而不僅僅是一個流浪的分號。你應該總是明確地評論這種情況,通常更好的做法是重寫你的代碼,以避免一個忙碌的等待循環。

+2

此外,大括號使意圖更清晰IMO。即使有適當的縮進,像'while(...); a ++;'(想象第一個''後的換行符; - 抱歉,不能在註釋中這樣做)很容易被誤讀爲在循環中增加'a'。這可能會讓代碼讀者感到困惑,或者更糟糕的是:有人可能會過來並在此之後刪除「;」,因爲他們認爲這就是您的意思。 – CompuChip

16

在這兩種情況下都會生成相同的字節碼。

我更喜歡使用{ }代替;,後者可有時有錯字的感覺,當它在forwhile循環的二手。

如果我有這樣的代碼:

while(i-- < j++); 
System.out.println("Wild World"); 

我也許會認爲這是一個錯字,;不應該在這裏。

但是,如果我有:

while(i-- < j++) { } 
System.out.println("Wild World"); 

我知道有一個原因..

7

良好的措施:

建立在其他兩個答案,我把代碼兩件在一個例子如下:

public class SO { 
public static void main(String[] args){ 
    int i=0,j=100; 

// Either a terminating ; symbol or {} braces work to make an "empty loop body". 
while (++i < --j) {} 
System.out.println("The midpoint between 0 and 100 is " +i); // Midpoint is 50. 
} 
} 

public class SO2 { 
public static void main(String[] args){ 
    int i=0,j=100; 

// Either a terminating ; symbol or {} braces work to make an "empty loop body". 
while (++i < --j) ; 
System.out.println("The midpoint between 0 and 100 is " +i); // Midpoint is 50. 
} 
} 

使用的javap -c我得到了以下的字節碼:

Compiled from "SO.java" 
public class SO { 
    public SO(); 
    Code: 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

    public static void main(java.lang.String[]); 
Code: 
    0: iconst_0 
    1: istore_1 
    2: bipush  100 
    4: istore_2 
    5: iinc   1, 1 
    8: iload_1 
    9: iinc   2, -1 
    12: iload_2 
    13: if_icmpge  19 
    16: goto   5 
    19: getstatic  #2     // Field java/lang/System.out:Ljava/io/PrintStream; 
    22: new   #3     // class java/lang/StringBuilder 
    25: dup 
    26: invokespecial #4     // Method java/lang/StringBuilder."<init>":()V 
    29: ldc   #5     // String The midpoint between 0 and 100 is 
    31: invokevirtual #6     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    34: iload_1 
    35: invokevirtual #7     // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 
    38: invokevirtual #8     // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    41: invokevirtual #9     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    44: return 
} 

Compiled from "SO2.java" 
public class SO2 { 
    public SO2(); 
    Code: 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

    public static void main(java.lang.String[]); 
Code: 
    0: iconst_0 
    1: istore_1 
    2: bipush  100 
    4: istore_2 
    5: iinc   1, 1 
    8: iload_1 
    9: iinc   2, -1 
    12: iload_2 
    13: if_icmpge  19 
    16: goto   5 
    19: getstatic  #2     // Field java/lang/System.out:Ljava/io/PrintStream; 
    22: new   #3     // class java/lang/StringBuilder 
    25: dup 
    26: invokespecial #4     // Method java/lang/StringBuilder."<init>":()V 
    29: ldc   #5     // String The midpoint between 0 and 100 is 
    31: invokevirtual #6     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    34: iload_1 
    35: invokevirtual #7     // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 
    38: invokevirtual #8     // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    41: invokevirtual #9     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    44: return 
} 

他們出現相同的言下之意,無論您選擇哪種方式,編譯器實現它完全一樣的。

3

這些在技術上是兩回事。一個是空的塊,一個是空的語句。

while(...) 
    statement; 

的Java會解釋這一點:

while(...) 
{ 
    statement; 
} 

這意味着

while(...);while(...){;}然後將其while(...){}

我的觀點:

雖然他們產生相同的字節碼(並且所有的意圖和目的都相同),它們實際上是兩個不同的東西,它們都通過一些java規則達到相同的結果。 {}實際上不是空(或空白)語句。這是一個空白的塊。循環後面必須跟着一個塊,因此空白語句被包裝到一個塊中,然後刪除空白語句。

相關問題