3

Java では、すべてのメソッド呼び出しがスタック上にあることを理解しています。たとえば、次のクラスを見てください。

Class Demo
{
   // Some instance variables
   public Demo()
   {
      initialize();
   }

   public void initialize()
   {
      // Start initialization
      ....

      // Call another method to perform some complex calculation
      int resultVal = helperMethod();

      // Perform the remaining initialization work

   }


   public int helperMethod()
   {
      // Perform some complex calculation 
      ....

      return result;
   }

}

最初initialize()に (その状態と共に) がスタックにプッシュされ、次にそれが呼び出されると helperMethod()、state forhelperMethod()もスタックにプッシュされます。

しかし、私が理解したいのは、メソッドではなくコンストラクターであるにもかかわらず、Demo() 最初にスタックにプッシュされる状態 (プッシュされる前) ですか?initialize()

コンストラクターの状態とメソッドの状態の保存に顕著な違いはありますか?

4

3 に答える 3

2

結局のところ、コンストラクターは他のメソッドと同じです。任意の型のパラメーターを取り、独自の型のオブジェクトを返します。他のものと同じようにコールスタックに置かれ、次のように表示されますDemo.<init>()

あなたの例のcall stack-traceの例外は次のようになります

Exception in thread "main" java.lang.NullPointerException
    at Demo.helperMethod(Demo.java:30)
    at Demo.initialize(Demo.java:16)
    at Demo.<init>(Demo.java:7)           <---------
    at Demo.main(Demo.java:36)
于 2015-07-24T21:24:27.470 に答える
2

Java言語の観点からは、これは実装固有です。JLSは、メソッドがスタックを必要とするかどうか、またはスタックがどのように見える必要があるかについてはあまり言いませんが、( 15.12.4.5で)フレームを作成できないためにメソッド呼び出しが発生しない場合は、 StackOverflowException をスローする必要があります。

Javaプラットフォーム(つまり、準拠する JVM によって実行される言語) の観点から見ると、コンストラクターメソッドであるため、スタック フレームに関する限り、同じように機能します。JVMS 2.9では、コンストラクターを「特別なメソッド」と説明していますが、スタックのフレーム性に関する限り、コンストラクターについて何も変更していません。

ご存知かもしれませんが、スタック オーバーフロー例外は、メソッドから戻らずにあまりにも多くのメソッドを呼び出すと発生します。実際には、これは無限再帰がある場合に最も一般的です。各オブジェクトが常にそれ自体の別のインスタンスを構築する場合 (つまり、構築の無限再帰)、コンストラクターでも同じ問題が発生する可能性があります。

public class ConsBoom {
  public ConsBoom() {
    new ConsBoom();
  }

  public static void main(String[] args) {
    new ConsBoom();
  }
}
于 2015-07-24T21:24:54.813 に答える
1

はい。コンストラクターの呼び出しは、通常のメソッドと同様にスタックを使用します。

于 2015-07-24T21:15:04.680 に答える