7

Javaの場合、これは次の場合です。

public void method() {
  if (condition) {
    Object x = ....;
  }
  System.out.println(x); // Error: x unavailable
}

私が疑問に思っているのは、これです。 -statementxのスコープに限定されているという事実ifは、Javaコンパイラの機能にすぎないのでしょうか、それとも-statementxの後で実際にスタックから削除されているのでしょうか。if

4

4 に答える 4

7

いいえ、コードブロックは個別のスタックフレームを取得しません。周囲のメソッドの1つを使用してください。

ただし、変数がスコープを離れると、現在のスタックフレームに配置され、他の変数に再利用できます。

スタックフレームの構造と使用法は、Java仮想マシン仕様§3.6フレームで説明されています。

メソッドが呼び出されるたびに、新しいフレームが作成されます。フレームは、メソッドの呼び出しが完了すると、その完了が正常であるか突然であるかに関係なく破棄されます(キャッチされない例外がスローされます)。

これは、メソッド呼び出しとフレームの間の1:1の関係を明確に指定します。

于 2010-06-17T11:31:13.893 に答える
2

ブロックはJava言語(構造化プログラミング言語)の一部ですが、コンパイルされたバイトコード(非構造化言語)の一部ではありません。

クラスファイルのメソッド指定は、実際の命令リストの上に、メソッドが合計で使用するローカル変数の数を指定します。しかし、Javaコードのどこにあるブロックがバイトコードから推測できない場合。

于 2010-06-17T11:33:44.647 に答える
1

まず、バイトコードでは、変数はスタックではなく、変数スロットと変数スロットに格納されます。スロットは別の変数で再利用できますが、変数スロットから値が削除される保証はありません。

たとえば、次のクラス

  public class A {
    public void method(boolean condition) {
 6    if (condition) {
 7      Object x = "";
 8      System.out.println(x);
 9    }
10    System.out.println(condition);
    }
  }

このバイトコードにコンパイルされます:

// class version 50.0 (50)
public class A {
  ...

  // access flags 0x1
  public method(Z)V
   L0
    LINENUMBER 6 L0
    ILOAD 1
    IFEQ L1
   L2
    LINENUMBER 7 L2
    LDC ""
    ASTORE 2
   L3
    LINENUMBER 8 L3
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 2
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L1
    LINENUMBER 10 L1
   FRAME SAME
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 1
    INVOKEVIRTUAL java/io/PrintStream.println (Z)V
   L4
    LINENUMBER 11 L4
    RETURN
   L5
    LOCALVARIABLE this LA; L0 L5 0
    LOCALVARIABLE condition Z L0 L5 1
    LOCALVARIABLE x Ljava/lang/Object; L3 L1 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

7行目で作成された変数xは、10行目に対応するバイトコードで引き続き使用可能な変数スロット2に格納されていることに注意してください。

Java言語をバイトコードにコンパイルする方法についての仕様はありませんが、いくつかの言語構造を適切にコンパイルする方法の例がいくつかあります。ただし、Javaコンパイラは未使用の変数を削除できます。たとえば、xが割り当てられているが、どこでも使用されていない場合、コンパイラはそのコードを削除できます。同様に、コンパイラはすべての静的定数をインライン化します。

于 2010-06-17T11:55:42.817 に答える
-1

はい、それは実際にスタックから削除され、以前は「x」で占められていたスロットを他のローカル変数で再利用できるようにします。

于 2010-06-17T11:35:33.130 に答える