15

我了解语句终止符符号;如果单独使用,则表示空语句。此外,“空循环体”可能是一种有用的编程结构,并且是使用空语句制成的。

看看下面的 while 语句,在第 2 行,我决定;用一对背靠背的{}花括号替换终止符号。代码编译并运行正常。这是否意味着 Java 编译器用基于 null 的语句替换了一个空代码块(由“空”{}花括号表示) ?;

如果 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.
4

4 回答 4

18

两者在语义上是相同的,编译器在两种情况下都会生成相同的代码。如果您试图故意包含一个空循环体,请{}更清楚地表明它是故意的,而不仅仅是一个杂散的分号。您应该始终明确地注释这种情况,并且通常最好重新编写代码以避免完全出现忙等待循环。

于 2013-11-25T11:54:23.853 回答
16

在这两种情况下都将生成相同的字节码。

我更喜欢使用{ }而不是,后者在和循环;中使用时有时会有错字的感觉。forwhile

如果我有这个代码:

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

我想也许这是一个错字,;不应该在这里。

但如果我有:

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

我知道这是有原因的。。

于 2013-11-25T11:54:41.977 回答
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
}

它们看起来相同,意味着无论您选择哪种方式,编译器都以完全相同的方式实现它。

于 2013-11-25T12:13:58.710 回答
3

从技术上讲,这是两个不同的东西。一个是空块,一个是空语句。

while(...)
    statement;

Java 将其解释为:

while(...)
{
    statement;
}

意思就是

while(...);while(...){;}那时while(...){}

我的观点:

虽然它们产生等效的字节码(并且对于所有意图和目的都是等效的),但它们实际上是两个不同的东西,它们都通过几个 java 规则得出相同的结果。{}真的不是一个空(或空白)语句。这是一个空块。While 循环后面必须跟一个块,因此将空白语句包装到块中,然后将空白语句删除。

于 2013-11-25T18:17:39.103 回答