15

;ステートメント ターミネータ シンボルを単独で使用すると、ヌル ステートメントを表すことを理解しています。また、「空のループ本体」は便利なプログラミング構造であり、null ステートメントを使用して作成されます。

以下の while ステートメントの 2 行目を見て、終了;記号を 1 対の背中合わせの{}中括弧に置き換えることにしました。コードはコンパイルされ、正常に実行されました。これは、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

この 2 つは意味的に同一であり、コンパイラはどちらの場合も同じコードを生成します。空のループ本体を意図的に含めようとしている場合{}は、単なるセミコロンではなく、意図的なものであることがより明確になります。そのような場合は常に明示的にコメントする必要があり、通常はコードを修正してビジー待機ループを完全に回避することをお勧めします。

于 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

適切な測定のために:

他の 2 つの回答に基づいて、次のように両方のコードを例に挙げます。

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 に答える